[英]Nested querying a xml document using LINQ in c#
我正在尝试使用LINQ将数据从xml文档检索到C#中的数组,其中我必须在xml数据的元素内使用一些嵌套查询,如下所示
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Catalog>
<Book ISBN="1.1.1.1" Genre="Thriller">
<Title Side="1">
<Pty R="1" ID="Seller_ID">
<Sub Typ="26" ID="John">
</Sub>
</Pty>
<Pty R="2" ID="ABC">
</Pty>
</Title>
</Book>
<Book ISBN="1.2.1.1" Genre="Thriller">
<Title Side="2">
<Pty R="1" ID="Buyer_ID">
<Sub Typ="26" ID="Brook">
</Sub>
</Pty>
<Pty R="2" ID="XYZ">
</Pty>
</Title>
</Book>
</Catalog>
在上面的XML文档中, Side="1"
代表卖方, Side="2"
代表卖方。 现在,我想将上述元素和属性存储在一个数组中,如下所示
阵列 ISBN类型发布日期买方_公司卖方_公司买方_经纪人卖方_经纪人
我能够检索常规元素和属性,但不确定如何处理依赖于其他元素(例如, Side, Pty and Sub
元素(例如Buyer_Company
)的其他元素,如Buyer_Company Seller_Company Buyer_Broker Seller_Broker)的属性是Pty的ID
属性,其中R= 2 and Side=2
。 同样, Buyer_Broker
是Sub
元素的ID
属性,其中其属性Typ=26
(可以有不同的Typ
值的XML数据),并且Sub
元素已经是R=1
Pty元素的子元素,而这又是Book
的子元素当Side=2
时的元素
我用来检索独立元素的代码是
var result = doc.Descendants("Book")
.Select(b => new
{
ISBN= b.Attribute("ISBN").Value,
Genre=b.Attribute("Genre").Value,
PublishDate= b.Element("Title").Attribute("MMY").Value,
})
.ToArray();
我在单个元素内进行查询,如下所示
Company= (string)b.Descendants("Pty")
.Where(e => (int)e.Attribute("R") == 7)
.Select(e => e.Attribute("ID"))
.Single()
但这没有考虑元素Book
的属性Side
。
样本数据
第一本书元素
ISBN:1.1.1.1
Genre:Thriller
Seller_Company:NULL
Seller_Broker:NULL
Buyer_Company:ABC
Buyer_Broker:John
第二本书元素
ISBN:1.1.1.1
Genre:Thriller
Seller_Company:XYZ
Seller_Broker:Brook
Buyer_Company: NULL
Buyer_Broker:NULL
side = 1代表卖方,而side = 2代表买方,这就是为什么卖方方在结果数组的第一个元素中为null,而买方方在第二个元素中为null
我可以知道解决此问题的更好方法吗?
您可以使用Parent
属性获取Pty
Parent
元素,然后获取Side
属性并进行检查:
.Where(e => (int)e.Attribute("R") == 7 &&
(int)e.Parent.Attribute("Side") == 2)
编辑以匹配问题:
使用XPath:
private static string GetCompanyValue(XElement bookElement, string side, string r)
{
string format = "Title[@Side={0}]/Pty[@R={1}]";
return GetValueByXPath(bookElement, string.Format(format, side, r));
}
private static string GetBrokerValue(XElement bookElement, string side)
{
string format = "Title[@Side={0}]/Pty[@R=1]/Sub[@Typ=26]";
return GetValueByXPath(bookElement, string.Format(format, side));
}
private static string GetValueByXPath(XElement bookElement, string expression)
{
XElement element = bookElement.XPathSelectElement(expression);
return element != null ? element.Attribute("ID").Value : null;
}
调用代码如下所示。
var result = doc.Descendants("Book")
.Select(book => new
{
ISBN = book.Attribute("ISBN").Value,
Genre = book.Attribute("Genre").Value,
Buyer_Company = GetCompanyValue(book, "2", "2"),
Buyer_Broker = GetBrokerValue(book, "2"),
Seller_Broker = GetBrokerValue(book, "1")
})
.ToArray();
向using System.Xml.XPath;
添加using语句using System.Xml.XPath;
现在,您已经提供了一些示例,我认为这对您有用。
const string xml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
<Catalog>
<Book ISBN=""1.1.1.1"" Genre=""Thriller"">
<Title Side=""1"">
<Pty R=""1"" ID=""Seller_ID"">
<Sub Typ=""26"" ID=""John"">
</Sub>
</Pty>
<Pty R=""2"" ID=""ABC"">
</Pty>
</Title>
</Book>
<Book ISBN=""1.2.1.1"" Genre=""Thriller"">
<Title Side=""2"">
<Pty R=""1"" ID=""Buyer_ID"">
<Sub Typ=""26"" ID=""Brook"">
</Sub>
</Pty>
<Pty R=""2"" ID=""XYZ"">
</Pty>
</Title>
</Book>
</Catalog>";
var doc = XDocument.Parse(xml);
var results = new List<object>();
foreach (var book in doc.Descendants("Book")) {
var title = book.Element("Title");
string buyerCompany = null;
string buyerBroker = null;
string sellerCompany = null;
string sellerBroker = null;
if (title.Attribute("Side").Value == "1") {
sellerCompany = title.Elements("Pty")
.Where(pty => pty.Attribute("R").Value == "2")
.Select(pty => pty.Attribute("ID").Value)
.FirstOrDefault();
sellerBroker = title.Elements("Pty")
.Where(pty => pty.Attribute("R").Value == "1")
.Select(pty => pty.Element("Sub").Attribute("ID").Value)
.FirstOrDefault();
} else if (title.Attribute("Side").Value == "2") {
buyerCompany = title.Elements("Pty")
.Where(pty => pty.Attribute("R").Value == "2")
.Select(pty => pty.Attribute("ID").Value)
.FirstOrDefault();
buyerBroker = title.Elements("Pty")
.Where(pty => pty.Attribute("R").Value == "1")
.Select(pty => pty.Element("Sub").Attribute("ID").Value)
.FirstOrDefault();
}
var result = new {
ISBN = book.Attribute("ISBN").Value,
Genre = book.Attribute("Genre").Value,
Seller_Company = sellerCompany,
Seller_Broker = sellerBroker,
Buyer_Company = buyerCompany,
Buyer_Broker = buyerBroker,
};
results.Add(result);
}
结果:
我认为您可能想按ISBN分组,然后有选择地从孩子那里获得价值。
const string xml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
<Catalog>
<Book ISBN=""1.1.1.1"" Genre=""Thriller"">
<Title Side=""1"" MMY=""000"">
<Pty R=""1"" ID=""Seller_ID"">
<Sub Typ=""26"" ID=""Seller_Broker"">
</Sub>
</Pty>
<Pty R=""2"" ID=""Seller_Company"">
</Pty>
</Title>
</Book>
<Book ISBN=""1.1.1.1"" Genre=""Thriller"">
<Title Side=""2"">
<Pty R=""1"" ID=""Buyer_ID"">
<Sub Typ=""26"" ID=""Buyer_Broker"">
</Sub>
</Pty>
<Pty R=""2"" ID=""Buyer_Company"">
</Pty>
</Title>
</Book>
</Catalog>";
var doc = XDocument.Parse(xml);
var results = doc.Descendants("Book")
.GroupBy(x => x.Attribute("ISBN").Value)
.Select(x => new {
ISBN = x.Key,
Genre = x.First().Attribute("Genre").Value,
PublishDate = x.First().Element("Title").Attribute("MMY").Value,
BuyerId = x.Where(book => book.Element("Title").Attribute("Side").Value == "2")
.First()
.Element("Title")
.Element("Pty")
.Attribute("ID").Value
})
.ToArray();
结果:
{
ISBN = "1.1.1.1",
Genre = "Thriller",
PublishDate = "000",
BuyerId = "Buyer_ID"
}
试试这个进行完整的解析
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var result = doc.Descendants("Book")
.Select(b => new
{
ISBN = b.Attribute("ISBN").Value,
Genre = b.Attribute("Genre").Value,
Side = b.Element("Title").Attribute("Side").Value,
ptr = b.Element("Title").Elements("Pty").Select(x => new {
R = x.Attribute("R").Value,
PtyID = x.Attribute("ID").Value,
Typ = x.Elements("Sub").Select(y => y == null ? null : y.Attribute("Typ").Value).FirstOrDefault(),
SubIDTyp = x.Elements("Sub").Select(y => y == null ? null : y.Attribute("ID").Value).FirstOrDefault()
}).ToList()
})
.ToList();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.