我们使用第三方Web服务返回XML,其外观类似于(为简洁起见):
<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>
对于特定产品代码,我需要获取realm
名称,即内部文本:
<a name="realm" format="text">
的 -u @ surfuk2 </a>
因为每个元素名称都是<block>
或<a>
,所以使用linq解析xml或查询表达式会有点麻烦。
以下是获取特定产品领域名称的最有效/最有效/最具表现力的方式,例如: 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;
答案 0 :(得分:2)
提供的realm
定义相当于更简单的:
string realm = (string) products.XPathEvaluate(
"string(
/*/blocks[@name='products']
/*/a[@name='product-id' and . = '1236']
/following-sibling::block[1]
)
"
)
这实际上比原始问题中提供的realm
定义更具可读性和更紧凑。
考虑到效率,很可能评估单个XPath表达式也会变得更有效率,但是如果发现这是真的,我们需要编写一个应用程序比较两种方法的时间。
答案 1 :(得分:0)
似乎如此,但为什么你需要所有的ToList()
电话?我看到其中三个电话,我认为不需要它们,所以它们只会减慢你的代码速度。但话说回来,我没有多少使用Linq-to-XMl。