Gewusst wie: Verknüpfen zweier Auflistungen (C#) (LINQ to XML)
Aktualisiert: November 2007
Ein Element oder Attribut in einem XML-Dokument kann mitunter auf ein anderes Element oder Attribut verweisen. So enthält z. B. das XML-Dokument in Kunden ('Customers') und Aufträge ('Orders') eine Liste von Kunden und eine Liste von Aufträgen. Jedes Customer-Element enthält ein CustomerID-Attribut. Jedes Order-Element enthält ein CustomerID-Element. Das CustomerID-Element eines Auftrags verweist auf das CustomerID-Attribut eines Kunden.
Das Thema XSD-Beispieldatei: Kunden ('Customers') und Aufträge ('Orders') enthält ein XSD-Schema, das zum Validieren dieses Dokuments verwendet werden kann. Mit den Features xs:key und xs:keyref des XSD-Schemas wird geprüft, ob das CustomerID-Attribut des Customer-Elements ein Schlüssel ist. Außerdem wird damit eine Beziehung zwischen dem CustomerID-Element in jedem Order-Element und dem CustomerID-Attribut in jedem Customer-Element hergestellt.
Mit LINQ to XML können Sie diese Beziehung durch Verwenden der join-Klausel nutzen.
Da es keinen Index gibt, führt eine solche Verknüpfung zu einer schlechten Laufzeitleistung.
Ausführlichere Informationen zu join finden Sie unter Verknüpfungsvorgänge.
Beispiel
Das folgende Beispiel verknüpft die Customer-Elemente mit den Order-Elementen und generiert ein neues XML-Dokument, das das CompanyName-Element der Aufträge enthält.
Vor dem Ausführen der Abfrage überprüft das Beispiel, ob das Dokument dem Schema in XSD-Beispieldatei: Kunden ('Customers') und Aufträge ('Orders') entspricht. Auf diese Weise wird sichergestellt, dass die JOIN-Klausel immer funktioniert.
Diese Abfrage ruft zuerst alle Customer-Elemente ab und verknüpft sie dann mit den Order-Elementen. Sie wählt dabei nur die Aufträge der Kunden aus, deren CustomerID größer als "K" ist. Anschließend projiziert die Abfrage ein neues Order-Element, das die Kundeninformationen in den einzelnen Aufträgen enthält.
In diesem Beispiel wird das XML-Dokument in XML-Beispieldatei: Kunden ('Customers') und Aufträge ('Orders') (LINQ to XML) verwendet.
In diesem Beispiel wird das XSD-Schema in XSD-Beispieldatei: Kunden ('Customers') und Aufträge ('Orders') verwendet.
Beachten Sie, dass diese Art von Verknüpfungen zu Leistungseinbußen führt. Verknüpfungen werden über eine lineare Suche ausgeführt. Es gibt keine Hashtabellen oder Indizes, die die Geschwindigkeit erhöhen könnten.
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", "CustomersOrders.xsd");
Console.Write("Attempting to validate, ");
XDocument custOrdDoc = XDocument.Load("CustomersOrders.xml");
bool errors = false;
custOrdDoc.Validate(schemas, (o, e) =>
{
Console.WriteLine("{0}", e.Message);
errors = true;
});
Console.WriteLine("custOrdDoc {0}", errors ? "did not validate" : "validated");
if (!errors)
{
// Join customers and orders, and create a new XML document with
// a different shape.
// The new document contains orders only for customers with a
// CustomerID > 'K'
XElement custOrd = custOrdDoc.Element("Root");
XElement newCustOrd = new XElement("Root",
from c in custOrd.Element("Customers").Elements("Customer")
join o in custOrd.Element("Orders").Elements("Order")
on (string)c.Attribute("CustomerID") equals
(string)o.Element("CustomerID")
where ((string)c.Attribute("CustomerID")).CompareTo("K") > 0
select new XElement("Order",
new XElement("CustomerID", (string)c.Attribute("CustomerID")),
new XElement("CompanyName", (string)c.Element("CompanyName")),
new XElement("ContactName", (string)c.Element("ContactName")),
new XElement("EmployeeID", (string)o.Element("EmployeeID")),
new XElement("OrderDate", (DateTime)o.Element("OrderDate"))
)
);
Console.WriteLine(newCustOrd);
}
Public Class Program
Public Shared errors As Boolean = False
Public Shared Function LamValidEvent(ByVal o As Object, _
ByVal e As ValidationEventArgs) As Boolean
Console.WriteLine("{0}", e.Message)
errors = True
End Function
Shared Sub Main()
Dim schemas As New XmlSchemaSet()
schemas.Add("", "CustomersOrders.xsd")
Console.Write("Attempting to validate, ")
Dim custOrdDoc As XDocument = XDocument.Load("CustomersOrders.xml")
custOrdDoc.Validate(schemas, Function(o, e) LamValidEvent(0, e))
If errors Then
Console.WriteLine("custOrdDoc did not validate")
Else
Console.WriteLine("custOrdDoc validated")
End If
If Not errors Then
'Join customers and orders, and create a new XML document with
' a different shape.
'The new document contains orders only for customers with a
' CustomerID > 'K'.
Dim custOrd As XElement = custOrdDoc.<Root>.FirstOrDefault
Dim newCustOrd As XElement = _
<Root>
<%= From c In custOrd.<Customers>.<Customer> _
Join o In custOrd.<Orders>.<Order> _
On c.@CustomerID Equals o.<CustomerID>.Value _
Where c.@CustomerID.CompareTo("K") > 0 _
Select _
<Order>
<CustomerID><%= c.@CustomerID %></CustomerID>
<%= c.<CompanyName> %>
<%= c.<ContactName> %>
<%= o.<EmployeeID> %>
<%= o.<OrderDate> %>
</Order> _
%>
</Root>
Console.WriteLine(newCustOrd)
End If
End Sub
End Class
Dieser Code erzeugt die folgende Ausgabe:
Attempting to validate, custOrdDoc validated
<Root>
<Order>
<CustomerID>LAZYK</CustomerID>
<CompanyName>Lazy K Kountry Store</CompanyName>
<ContactName>John Steel</ContactName>
<EmployeeID>1</EmployeeID>
<OrderDate>1997-03-21T00:00:00</OrderDate>
</Order>
<Order>
<CustomerID>LAZYK</CustomerID>
<CompanyName>Lazy K Kountry Store</CompanyName>
<ContactName>John Steel</ContactName>
<EmployeeID>8</EmployeeID>
<OrderDate>1997-05-22T00:00:00</OrderDate>
</Order>
<Order>
<CustomerID>LETSS</CustomerID>
<CompanyName>Let's Stop N Shop</CompanyName>
<ContactName>Jaime Yorres</ContactName>
<EmployeeID>1</EmployeeID>
<OrderDate>1997-06-25T00:00:00</OrderDate>
</Order>
<Order>
<CustomerID>LETSS</CustomerID>
<CompanyName>Let's Stop N Shop</CompanyName>
<ContactName>Jaime Yorres</ContactName>
<EmployeeID>8</EmployeeID>
<OrderDate>1997-10-27T00:00:00</OrderDate>
</Order>
<Order>
<CustomerID>LETSS</CustomerID>
<CompanyName>Let's Stop N Shop</CompanyName>
<ContactName>Jaime Yorres</ContactName>
<EmployeeID>6</EmployeeID>
<OrderDate>1997-11-10T00:00:00</OrderDate>
</Order>
<Order>
<CustomerID>LETSS</CustomerID>
<CompanyName>Let's Stop N Shop</CompanyName>
<ContactName>Jaime Yorres</ContactName>
<EmployeeID>4</EmployeeID>
<OrderDate>1998-02-12T00:00:00</OrderDate>
</Order>
</Root>