c# - 使用LINQ查询XDocument,如何获取具体值?
问题描述
我正在尝试重构以下内容-可行,但是如果我开始在 XML 中获取更多元素,它将变得难以管理:
HttpResponseMessage response = await httpClient.GetAsync("https://uri/products.xml");
string responseAsString = await response.Content.ReadAsStringAsync();
List<Product> productList = new List<Product>();
XDocument xdocument = XDocument.Parse(responseAsString);
var products = xdocument.Descendants().Where(p => p.Name.LocalName == "item");
foreach(var product in products)
{
var thisProduct = new Product();
foreach (XElement el in product.Nodes())
{
if(el.Name.LocalName == "id")
{
thisProduct.SKU = el.Value.Replace("-master", "");
}
if (el.Name.LocalName == "availability")
{
thisProduct.Availability = el.Value == "in stock";
}
}
productList.Add(thisProduct);
}
给定以下 XML URL
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://base.google.com/ns/1.0" version="0">
<channel>
<title>Product Feed</title>
<link></link>
<description>Products</description>
<item>
<availability>in stock</availability>
<id>01234-master</id>
...
</item>
<item>
<availability>in stock</availability>
<id>abcde-master</id>
...
</item>
</channel>
</rss>
理想情况下,我想删除循环和 if 语句,并有一个 LINQ 查询,它以一种干净的方式从 XML 中只返回我需要的字段(id、可用性等),并用这些数据填充一个简单的类。
任何人都可以帮忙吗?
解决方案
有时您必须为自己编写的代码感到高兴。有时没有“更聪明”的写法……你只能写得“更好”一点:
List<Product> productList = new List<Product>();
XDocument xdocument = XDocument.Parse(responseAsString);
XNamespace ns = "http://base.google.com/ns/1.0";
var products = from x in xdocument.Elements(ns + "rss")
from y in x.Elements(ns + "channel")
from z in y.Elements(ns + "item")
select z;
foreach (var product in products)
{
var prod = new Product();
productList.Add(prod);
foreach (XElement el in product.Elements())
{
if (el.Name == ns + "id")
{
prod.SKU = el.Value.Replace("-master", string.Empty);
}
else if (el.Name == ns + "availability")
{
prod.Availability = el.Value == "in stock";
}
}
}
笔记:
- 这
Descendants()
在道德上是错误的。item
意志有一个固定的位置/rss/channel/item
,你非常清楚。它不是//item
。因为明天可能会有一个rss/foo/item
今天不存在的东西。您尝试编写代码,以便它与可以添加到 xml 的其他信息前向兼容。 我确实讨厌 xml 命名空间......并且有多个嵌套命名空间的 xml。我多么讨厌那些。但是比我更聪明的人认为它们存在。我接受。我使用它们进行编码。在 LINQ-to-XML 中,这很容易。有一个
XNamespace
甚至有一个重载的+
运算符。注意,如果你是一个微优化器(我尽量不要,但我不得不承认,但我的手有点痒),你可以预先计算循环
ns + "xxx"
内使用的各种for
,因为它不是从这里清除,但它们在每个周期都被重建。一个XName
内部是如何构建的……哦……那是一件令人着迷的事情,相信我。private static readonly XNamespace googleNs = "http://base.google.com/ns/1.0"; private static readonly XName idName = googleNs + "id"; private static readonly XName availabilityName = googleNs + "availability";
接着
if (el.Name == idName) { prod.SKU = el.Value.Replace("-master", string.Empty); } else if (el.Name == availabilityName) { prod.Availability = el.Value == "in stock"; }
推荐阅读
- gulp - 无法使用 Gulp 编译资产
- java - 链式 CompletableFuture 的内存管理
- git - Git one-liner 恢复不需要的子模块更改
- firebase - 具有自定义域名的 Firebase 托管仍使用“xxx.firebaseapp.com”
- r - 我需要找到一种方法来计算值 x 的重复次数,其中另一列值为 y
- python - 如何使用 Pandas DateTime 识别 EDA 期间的时间差异
- hibernate - 从新/新到加载实体的休眠关联管理不一致 - 为什么?
- python - 列表理解语法 - 如何使用 ... if ... else?
- sql - 如何在 SQL Server 中将 int 转换或强制转换为字符串
- javascript - 解析服务器云异步函数不返回结果