微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用多个XPath查询在c#中选择单个XML节点

如何解决如何使用多个XPath查询在c#中选择单个XML节点

我试图基于两个查询从XML文件中选择一个节点,我有一个产品ID,我需要该产品的最新条目-最高发行编号。

这是我的XML文件的格式:

<MyProducts>  
  <Product code="1011234">
    <ProductName>Product Name A</ProductName>
    <ProductId>101</ProductId>
    <IssueNumber>1234</IssueNumber>
  </Product>
  <Product code="1029999">
    <ProductName>Product Name B</ProductName>
    <ProductId>102</ProductId>
    <IssueNumber>9999</IssueNumber>
  </Product>
  <Product code="1015678">
    <ProductName>Product Name A2</ProductName>
    <ProductId>101</ProductId>
    <IssueNumber>5678</IssueNumber>
  </Product>
</MyProducts>

我需要从具有最高IssueNumber的ProductId中获取<product>节点。例如,如果ProductId为101,则我想要第三个节点;如果为102,则我想要第二个节点。文件中大约有50种不同的产品,分为三个不同的产品ID。

我已经通过使用特定的ProductID和IssueNumber节点,或者通过使用产品节点的code属性(Id和Issue的组合)使用SelectSingleNode尝试了许多XPath组合,但是没有成功。 该代码当前使用code属性,但这仅是因为我们还传递了问题编号,并且我希望能够在没有问题编号的情况下执行此操作(以减少前端维护),因为它始终是我们想要的最高问题。 当前代码是这样的:

XmlNode productNode = productXml.SelectSingleNode("/MyProducts/Product[@code='" + productCode + "']");

我也使用了这些,它们的工作方式不错,但是选择内部节点,而不是外部Product节点:

XmlNodeList productNodes = productXml.SelectNodes("/MyProducts/Product/ProductId[text()='101']");
XmlNodeList productNodes = productXml.SelectNodes("/MyProducts/Product[not (../Product/IssueNumber > IssueNumber)]/IssueNumber");

我想将两者结合使用,就像这样:

XmlNode productNode = productXml.SelectSingleNode("/MyProducts/Product/ProductId[text()='101'] and /MyProducts/Product[not (../Product/IssueNumber > IssueNumber)]/IssueNumber");

但是返回错误“ ...引发类型'System.Xml.XPath.XPathException'的异常”,但我也希望它始终不会返回Product节点。 甚至可以单行完成,还是我必须遍历节点以找到正确的节点?

解决方法

使用Xml Linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication167
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            var products = doc.Descendants("Product")
                .OrderByDescending(x => (int)x.Element("IssueNumber"))
                .GroupBy(x => (int)x.Element("ProductId"))
                .Select(x => x.First())
                .ToList();

            Dictionary<int,XElement> dict = products
                .GroupBy(x => (int)x.Element("ProductId"),y => y)
                .ToDictionary(x => x.Key,y => y.FirstOrDefault());

            XElement highestId = dict[101];

        }
    }


 
}
,

您的最后一个想法几乎就在那里。您需要将两个子句 放在[]选择器中。我认为max()也可用,可以阐明逻辑。这应该起作用:

/MyProducts/Product[ProductId='101'
   and IssueNumber=max(/MyProducts/Product[ProductId='101']/IssueNumber)]

这将选择{em> 都具有ID 101 在所有id-101产品中具有最高IssueNumber的Product

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。