2009-01-12 5 views
5

Wir verwenden einen Dritten Web-Service, XML zurückgibt, die wie etwas aussieht (Schnitt der Kürze nach unten):Ist dies die effizienteste Möglichkeit, diese XDocument-Abfrage auszudrücken?

<Response> 
    <block name="availability"> 
    <block name="cqual"> 
     <a name="result-code" format="text">L</a> 
    </block> 
    <block name="exchange"> 
     <a name="code" format="text">MRDEN</a> 
    </block> 
    <block name="mqual"> 
     <a name="rate-adaptive" format="text">G</a> 
    </block> 
    </block> 
    <block name="products"> 
    <block> 
     <a name="product-id" format="counting">1235</a> 
     <block name="realms"> 
     <block> 
      <a name="realm" format="text">[email protected]</a> 
     </block> 
     </block> 
    </block> 
    <block> 
     <a name="product-id" format="counting">1236</a> 
     <block name="realms"> 
     <block> 
      <a name="realm" format="text">[email protected]</a> 
     </block> 
     </block> 
    </block> 
    <block> 
     <a name="product-id" format="counting">1237</a> 
     <block name="realms"> 
     <block> 
      <a name="realm" format="text">[email protected]</a> 
     </block> 
     </block> 
    </block> 
    </block> 
    <status no="0" /> 
</Response> 

Für einen bestimmten Code Produkt, das ich den realm Namen dh der Innentext erhalten müssen:

<a name="realm" format="text">-u @ surfuk2</a>

Da jedes Element Name ist entweder <block> oder <a> es ist ein bisschen mühsam mit Linq zu analysieren zu XML- oder Abfrageausdrücken.

Ist das Folgende der effektivste/effizienteste/aussagekräftigste Weg, um den Realm-Namen für ein bestimmtes Produkt zu erhalten, z.B. 1235:

List<XElement> products = response 
    .Element("Response") 
    .Elements("block") 
    .Where(x => x.Attribute("name").Value == "products") 
    .Elements("block").ToList(); 
// 
// I broke down the query to aid readability 
// 
string realm = products.Elements("a") 
    .Where(x => x.Attribute("name").Value == "product-id") 
    .Where(y => y.Value == "1235") // hardcoded for example use 
    .Ancestors() 
    .First() 
    .Elements("block") 
    .Where(z => z.Attribute("name").Value == "realms") 
    .Elements("block") 
    .Elements("a") 
    .First().Value; 

Antwort

2

Die Definition von realm wie vorgesehen, um das Äquivalent der einfacheren:

string realm = (string) products.XPathEvaluate(
    "string(
     /*/blocks[@name='products'] 
       /*/a[@name='product-id' and . = '1236'] 
           /following-sibling::block[1] 
     ) 
    " 
            ) 

Dies ist in der Tat sowohl lesbare und kompaktere als die Definition von realm in der ursprünglichen Frage vorgesehen.

Da Effizienz betrifft, könnte es gut sein, dass Auswertung eines einzelnen XPath-Ausdruckes könnte auch effizienter zu sein, aber zu finden, wenn dies wahr ist, müssen wir eine Anwendung schreiben, die die Zeiten vergleichen wird die zwei Methoden.

+0

Danke für die Antwort. Ich weiß, dass ich mit XPath viel prägnanter sein könnte, aber ich dachte mir, dass ich meine LINQ-Beine heute dehnen sollte :-) – Kev

0

Es scheint so, aber warum müssen Sie alle der ToList() Anrufe? Ich sehe drei dieser Anrufe und ich denke nicht, dass sie benötigt werden, also verlangsamen sie einfach Ihren Code. Aber andererseits habe ich nicht viel Linq-to-XMl verwendet.

+0

Eh ... gab es Reste von einer Debugging-Sitzung. Sortiert jetzt. – Kev

Verwandte Themen