簡體   English   中英

如何使用多個 XPath 查詢在 c# 中選擇單個 XML 節點

[英]How to select a single XML node in c# using multiple XPath queries

我試圖從基於兩個查詢的 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。

我已經使用 SelectSingleNode 嘗試了許多 XPath 組合,方法是使用特定的 ProductID 和 IssueNumber 節點,或者使用產品節點的 code 屬性(它是 Id 和 Issue 的組合),但沒有成功。 代碼當前使用 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)]

這將選擇Product ,其既有ID 101具有所有ID-101產品的最高IssueNumber。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM