We utilise a third party web service that returns XML which looks something like (cut down for brevity):
<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">-u@surfuk1</a>
</block>
</block>
</block>
<block>
<a name="product-id" format="counting">1236</a>
<block name="realms">
<block>
<a name="realm" format="text">-u@surfuk2</a>
</block>
</block>
</block>
<block>
<a name="product-id" format="counting">1237</a>
<block name="realms">
<block>
<a name="realm" format="text">-u@surfuk3</a>
</block>
</block>
</block>
</block>
<status no="0" />
</Response>
For a specific product code I need to obtain the realm
name i.e. the inner text of:
<a name="realm" format="text">
-u@surfuk2</a>
Because every element name is either <block>
or <a>
it's a bit troublesome to parse with linq to xml or query expressions.
Is the following the most effective/efficient/expressive way to get at the realm name for a specific product, e.g. 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;
The definition of realm
as provided is the equivalent of the simpler:
string realm = (string) products.XPathEvaluate(
"string(
/*/blocks[@name='products']
/*/a[@name='product-id' and . = '1236']
/following-sibling::block[1]
)
"
)
This in fact is both more readable and more compact than the definition of realm
provided in the original question.
As efficiency is concerned, it could well be that evaluating a single XPath expression may turn out to be more efficient, too, however to find if this is true we need to write an application that will compare the timings of the two methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With