2009-07-23 12 views
1

Wir haben eine XML-Datei mit einer sehr einfachen Implementierung von XLink implementieren:Wie eine einfache XPath-Lookup

<root xmlns:xlink="http://www.w3.org/1999/xlink"> 
    <firstChild id="ID1" /> 
    ... 
    <ref xlink:href="#ID1" /> 
</root> 

Nehmen wir an, die XLink Implementierung als dass jede komplizierter wird es nicht. Der wichtige Punkt ist jedoch, dass das Element, auf das verwiesen wird (in diesem Fall firstChild), irgendwo im Dokument an beliebiger Stelle in der Hierarchie angezeigt werden kann.

In einem XPath-Nachschlag Sie das Element auf die sich die < ref> Knoten unter Verwendung eines Ausdrucks wie finden konnte:

//*[@id='ID1'] 

Was ist der beste gleichwertig mit LINQ to XML? Ich hätte etwas in diese Richtung gedacht:

XDocument doc = XDocument.Load("file.xml"); 
var dest = xDoc.Descendants().Where(e => (string)e.Attribute("id") == "ID1").SingleOrDefault(); 

Ich habe es tatsächlich noch nicht getestet. Aber im Allgemeinen, wenn das XML-Dokument ziemlich groß ist, wird der LINQ Weg ineffizient sein (da es eine Enumeration aller Nachkommen auf dem XDocument verwendet)? Wäre es besser, zu einem XPathNavigator zurückzukehren und nur den XPath-Ausdruck zu verwenden?

Wenn so etwas in LINQ zu tun ist, gibt es eine bessere Methode als das, was ich geschrieben habe? LINQ ist für mich noch ein paar Tage alt ... Es ist großartig, aber ich frage mich, ob es bei bestimmten Operationen Effizienzeinschränkungen gibt.

Antwort

3

XPathNavigator wird hier nicht effizienter, weil es immer noch alle Nachkommen aufzählen muss, um sie zu finden - es gibt keinen magischen Staub dort. Wenn Sie möchten, dass es effizienter ist, benötigen Sie einen Index, und keine integrierte XML-API stellt sie bereit, sodass Sie Ihre eigenen bereitstellen müssen. Zum Beispiel:

und dann dieses Wörterbuch verwenden, um Knoten nach ID zu suchen, wann immer Sie möchten. Offensichtlich ist dies nur sinnvoll, wenn Nachschläge relativ häufig sind und nicht, wenn Sie es nur ein oder zwei Mal tun müssen.

+0

Genau das, was ich gesucht :) –

1

Wenn ich du wäre, würde ich es auf die gleiche Weise tun. Außer in der Where-Klausel:

from e in xDoc.Descendants() 
let id = e.Attribute("id") ? e.Attribute("id").Value : null 
where (id == "ID") 
select e 

So ist es nicht notwendig, das Gießen zu tun.

In Bezug auf Ihre erste Frage, soweit ich weiß, Microsoft die Entwicklung auf der XPath Implementierung gestoppt, so glaube ich, auch im Moment nicht, die LINQ  -  XML würde eine viel bessere Optimierung zu XPath verglichen hat.

+0

Das wird 'NullReferenceException' werfen, wenn einige Knoten in dem Dokument nicht' @ Auch id' –

+1

haben, gibt es keine „Optimierung“ in entweder XPath (wie umgesetzt in XPathNavigator) oder LINQ! Es ist keine Magie. Es funktioniert genau so, wie Sie es erwarten, nämlich lineare Scans überall. Es kann keine Indizes verwenden, denn woher weiß es, was Sie suchen und was Sie indizieren? Wenn überhaupt, kann XPathNavigator für einige Arten von Abfragen tatsächlich schneller sein, da seine Knoten doppelt verknüpft sind und XLINQ-Einsen einfach verknüpft sind (in XPathDocument erhalten Sie also die vorangestellten Geschwister mit O (1), aber in XLINQ mit O (N)). . –

+0

Optimierung bedeutet, wie MS die Codes implementiert. Es ist das gleiche wie jeder Browser die JS-Engine implementiert, und es kommt derzeit Safari, Chrome die Geschwindigkeit und IE kommt zuletzt.Sie alle haben den gleichen JS-Code getestet und der einzige Unterschied besteht darin, wie die Ausführungsstrategie und die Algorithmen des Browsers funktionieren. Die Optimierung, die ich sagte, ist die gleiche Sache, MS wird sich bemühen, LINQ schnell (er) laufen zu lassen. – xandy

0
from e in doc.Descendants() 
where (string)e.Attribute("id") != null 
select e; 
Verwandte Themen