如何仅处理某些 XML 节点

本文关键字:XML 节点 何仅 处理 | 更新日期: 2023-09-27 18:25:47

这是我的XML代码段(它有一个根元素(。

<ItemAttributes>
    <Author>Ellen Galinsky</Author>
    <Binding>Paperback</Binding>
    <Brand>Harper Paperbacks</Brand>
    <EAN>9780061732324</EAN>
    <EANList>
        <EANListElement>9780061732324</EANListElement>
    </EANList>
    <Edition>1</Edition>
    <Feature>ISBN13: 9780061732324</Feature>
    <Feature>Condition: New</Feature>
    <Feature>Notes: BRAND NEW FROM PUBLISHER! 100% Satisfaction Guarantee. Tracking provided on most orders. Buy with Confidence! Millions of books sold!</Feature>
    <ISBN>006173232X</ISBN>
    <IsEligibleForTradeIn>1</IsEligibleForTradeIn>
    <ItemDimensions>
        <Height Units="hundredths-inches">112</Height>
        <Length Units="hundredths-inches">904</Length>
        <Weight Units="hundredths-pounds">98</Weight>
        <Width Units="hundredths-inches">602</Width>
    </ItemDimensions>
    <Label>William Morrow Paperbacks</Label>
    <ListPrice>
        <Amount>1699</Amount>
        <CurrencyCode>USD</CurrencyCode>
        <FormattedPrice>$16.99</FormattedPrice>
    </ListPrice>
    <Manufacturer>William Morrow Paperbacks</Manufacturer>
    <MPN>006173232X</MPN>
    <NumberOfItems>1</NumberOfItems>
    <NumberOfPages>400</NumberOfPages>
    <PackageDimensions>
        <Height Units="hundredths-inches">120</Height>
        <Length Units="hundredths-inches">880</Length>
        <Weight Units="hundredths-pounds">95</Weight>
        <Width Units="hundredths-inches">590</Width>
    </PackageDimensions>
    <PartNumber>006173232X</PartNumber>
    <ProductGroup>Book</ProductGroup>
    <ProductTypeName>ABIS_BOOK</ProductTypeName>
    <PublicationDate>2010-04-20</PublicationDate>
    <Publisher>William Morrow Paperbacks</Publisher>
    <ReleaseDate>2010-04-20</ReleaseDate>
    <SKU>mon0000013657</SKU>
    <Studio>William Morrow Paperbacks</Studio>
    <Title>Mind in the Making: The Seven Essential Life Skills Every Child Needs</Title>
</ItemAttributes>

有多个"项目属性"节点,每个节点都有不同的"产品组"节点。 我只想要第一个"项目属性",其中"产品组"="书:">

这是我的 C# 代码:

    XPathDocument doc = new XPathDocument(sr);
    XPathNavigator nav = doc.CreateNavigator();
    // Compile a standard XPath expression
    XPathExpression expr;
    expr = nav.Compile("//ItemAttributes[contains(ProductGroup, 'Book')]");
    XPathNodeIterator iterator = nav.Select(expr);
    // Iterate on the node set
    try {
        int x = iterator.Count;  //  <----------- count = 0
        while (iterator.MoveNext()) {  //  <-----------  finds nothing!
            XPathNavigator nav2 = iterator.Current.Clone();
            listBox1.Items.Add("price: " + nav2.Value);
        }
    }
    catch (Exception ex) {
        Console.WriteLine(ex.Message);
    }

我知道我的代码不正确,但我不明白为什么迭代器。计数为零!

如何仅处理某些 XML 节点

使用System.Xml.Linq

XDocument xdoc = XDocument.Load(new StringReader(xmlstr)); 
var foundNode = xdoc
    .Descendants("ItemAttributes")
    .Where(node => node.Element("ProductGroup").Value == "Book")
    .First();
var price = foundNode.Element("ListPrice").Element("FormattedPrice").Value;

--编辑--

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            string xmlstr = @"
                    <root>
                    <ItemAttributes>
                    <Author>Ellen Galinsky</Author>
                    <Binding>Paperback</Binding>
                    <Brand>Harper Paperbacks</Brand>
                    <EAN>9780061732324</EAN>
                    <EANList>
                    <EANListElement>9780061732324</EANListElement>
                    </EANList><Edition>1</Edition>
                    <Feature>ISBN13: 9780061732324</Feature>
                    <Feature>Condition: New</Feature>
                    <Feature>Notes: BRAND NEW FROM PUBLISHER! 100% Satisfaction Guarantee. Tracking provided on most orders. Buy with Confidence! Millions of books sold!</Feature>
                    <ISBN>006173232X</ISBN>
                    <IsEligibleForTradeIn>1</IsEligibleForTradeIn>
                    <ItemDimensions>
                    <Height Units=""hundredths-inches"">112</Height>
                    <Length Units=""hundredths-inches"">904</Length>
                    <Weight Units=""hundredths-pounds"">98</Weight>
                    <Width Units=""hundredths-inches"">602</Width>
                    </ItemDimensions>
                    <Label>William Morrow Paperbacks</Label>
                    <ListPrice>
                    <Amount>1699</Amount>
                    <CurrencyCode>USD</CurrencyCode>
                    <FormattedPrice>$16.99</FormattedPrice>
                    </ListPrice>
                    <Manufacturer>William Morrow Paperbacks</Manufacturer>
                    <MPN>006173232X</MPN>
                    <NumberOfItems>1</NumberOfItems>
                    <NumberOfPages>400</NumberOfPages>
                    <PackageDimensions>
                    <Height Units=""hundredths-inches"">120</Height>
                    <Length Units=""hundredths-inches"">880</Length>
                    <Weight Units=""hundredths-pounds"">95</Weight>
                    <Width Units=""hundredths-inches"">590</Width>
                    </PackageDimensions>
                    <PartNumber>006173232X</PartNumber>
                    <ProductGroup>Book</ProductGroup>
                    <ProductTypeName>ABIS_BOOK</ProductTypeName>
                    <PublicationDate>2010-04-20</PublicationDate>
                    <Publisher>William Morrow Paperbacks</Publisher>
                    <ReleaseDate>2010-04-20</ReleaseDate>
                    <SKU>mon0000013657</SKU>
                    <Studio>William Morrow Paperbacks</Studio>
                    <Title>Mind in the Making: The Seven Essential Life Skills Every Child Needs</Title>
                    </ItemAttributes>
                    </root>
                    ";
            XDocument xdoc = XDocument.Load(new StringReader(xmlstr));
            var foundNode = xdoc
                .Descendants("ItemAttributes")
                .Where(node => node.Element("ProductGroup").Value == "Book")
                .First();
            Console.WriteLine(foundNode.Element("ListPrice").Element("FormattedPrice").Value);
            Console.ReadLine();
        }
    }
}
-

-编辑2--

XDocument xdoc = XDocument.Load("http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=AKIAIAAFYAPOR6SX5GOA&AssociateTag=pragbook-20&IdType=ISBN&ItemId=9780061732324&MerchantId=All&Operation=ItemLookup&ResponseGroup=Medium&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2012-02-26T20%3A18%3A37Z&Version=2011-08-01&Signature=r7yE7BQI44CqWZAiK%2FWumF3N4iutOj3re9wZtESOaKs%3D");
XNamespace ns = XNamespace.Get("http://webservices.amazon.com/AWSECommerceService/2011-08-01");
var foundNode = xdoc
    .Descendants(ns+"ItemAttributes")
    .Where(node => node.Element(ns+"ProductGroup").Value == "Book")
    .First();
Console.WriteLine(foundNode.Element(ns+"ListPrice").Element(ns+"FormattedPrice").Value);
Console.ReadLine();

我会使用 XPath 和 XmlDocument 来处理这个问题。

XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(myXMLString);
XmlNodeList nodeList = xDoc.SelectNodes("//ItemAttributes[./ProductGroup[text()='Book']]");
foreach (XmlNode node in nodeList)
{
  //Do anything with node.Value;
}

我没有尝试过你的代码,但从我所看到的你的 XPath 表达式不正确。我已经分解了我在下面写的表达。

它读作

//ItemAttributes    #look for all nodes named ItemAttributes
[
    ./ProductGroup  #with a child node called ProductGroup
    [
      text()='Book' #that has the string 'Book' as the text
    ]
]

你说你的XML是一个片段。 我冒昧地猜测它包含在将默认命名空间前缀绑定到非平凡 URI 的元素中,这就是为什么您没有从迭代器中获得任何结果的原因。

您的代码对我有用,上面给出的XML文档。 我运行了代码并从迭代器中获取了一个元素。 然后,我拿起您的 XML 文档并将其包装在一个根元素中,该根元素将默认命名空间前缀绑定到一个虚构但非平凡的 URI:

<SomeRootElement xmlns="http://schemas.blahblahblah.com/example">
  <ItemAttributes>
    <!-- rest of your document omitted -->
  </ItemAttributes>
</SomeRootElement>   

然后我从迭代器中没有得到任何结果。

然后,我创建了一个 XmlNamespaceManager,它将前缀(我选择了 pfx(映射到上面使用的命名空间 URI:

XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable());
mgr.AddNamespace("pfx", "http://schemas.blahblahblah.com/example");

然后,我将此命名空间管理器设置为 XPath 表达式的命名空间上下文,并将前缀pfx添加到 XPath 表达式中的名称:

XPathExpression expr;
expr = nav.Compile("//pfx:ItemAttributes[contains(pfx:ProductGroup, 'Book')]");
expr.SetContext(mgr);
XPathNodeIterator iterator = nav.Select(expr);

然后,正如预期的那样,我从迭代器中取出了一个元素。


XPath 对于命名空间可能有点有趣。 我尝试将空前缀""绑定到 URI,以便我可以未经修改地使用您的 XPath 表达式,但这不起作用。 这是我以前在 XPath 中发现的一件事:始终将命名空间 URI 绑定到 XPath 的前缀,即使原始 XML 文档绑定了默认命名空间前缀。 XPath 中不带前缀的名称似乎始终位于"null"命名空间中。

我还没有真正研究过如何在 .NET 中使用 XPath 将命名空间前缀映射到 URI,并且可能比我在快速谷歌搜索和阅读 MSDN 后拼凑起来的方法更好。

编辑:我回答的目的是解释为什么你的代码使用XPath不起作用。 你不明白为什么你没有从迭代器中获得任何结果。 我怀疑你没有给我完整的XML文档,并且在你没有与我们分享的文档部分奠定了答案。

最终,我相信您的原始代码由于 XML 命名空间而不起作用。 在我撰写此编辑时,我只能从您使用 L.B 的评论线程中的 URL 中收到"请求已过期"错误,因此我无法再使用您正在使用的相同类型的数据进行测试。 但是,此错误请求的开头如下所示:

<?xml version="1.0"?>
<ItemLookupErrorResponse xmlns="http://ecs.amazonaws.com/doc/2011-08-01/">

xmlns 属性将元素以及其中包含的每个元素放入命名空间中。 每个命名空间都由一个 URI 标识,URI 和元素名称一起标识该元素。

可能是成功的请求可能具有相同的属性。 但是,L.B.的答案使用了不同的命名空间,所以我不能确定。 对于此编辑的其余部分,我必须假设成功的请求确实包含与不成功的请求相同的命名空间。

由于此命名空间,元素<ItemAttributes>在此 XML 中

<ItemLookupResponse xmlns="http://ecs.amazonaws.com/doc/2011-08-01/">
  <ItemAttributes />
</ItemLookupResponse>

并在此 XML 中

<ItemAttributes />

不一样。 第一个位于 http://ecs.amazonaws.com/doc/2011-08-01/ 命名空间中,而第二个位于由空字符串标识的命名空间中。 此空命名空间是默认命名空间(如果尚未以任何其他方式设置(。

由于两个ItemAttributes元素具有不同的命名空间,因此它们并不相同。

除了使用 xmlns="..." 更改元素的命名空间外,您还可以将前缀关联(或绑定(到命名空间。 这是通过使用 xmlns:prefix="some-uri" 等属性在 xmlns 属性中指定要与命名空间关联的前缀来完成的。 然后将此前缀放入 XML 元素的本地名称之前,例如 <prefix:SomeElement ... /> 。 这会将 SomeElement 元素放在与 URI some-uri 关联的命名空间中。

由于元素由本地名称和命名空间 URI 标识,因此以下两个 XML 片段是相等的,即使一个使用前缀而另一个不使用前缀也是如此:

<ItemLookupResponse xmlns="http://ecs.amazonaws.com/doc/2011-08-01/">
  <ItemAttributes />
</ItemLookupResponse>
<ecs:ItemLookupResponse xmlns:ecs="http://ecs.amazonaws.com/doc/2011-08-01/">
  <ecs:ItemAttributes />
</ecs:ItemLookupResponse>

现在我们转向 XPath 和命名空间。 您的 XPath 表达式是

//ItemAttributes[contains(ProductGroup, 'Book')]

XPath 的一个恼火是,您不能像使用 XML 那样更改不使用前缀的命名空间。 因此,上面ItemAttributesProductGroup的名称始终位于"空"命名空间中。 此 XPath 表达式与 XML 文档中的任何内容都不匹配,因为"空"命名空间中没有具有本地名称ItemAttributes元素,更不用说任何具有包含文本BookProductGroup子元素的元素了。

但是,对于大多数(如果不是全部(XPath API,有一些方法可以将前缀绑定到命名空间。 我所做的是展示一种在 .NET 中使用 XPath 执行此操作的方法。 我将前缀pfx(我可以选择任何我想要的前缀(与我在上面示例中使用的 URI 相关联。 您将使用与我虚构的示例不同的 URI。 然后,您可以使用 XPath 表达式

//pfx:ItemAttributes[contains(pfx:ProductGroup, 'Book')]

查找相关元素,因为存在名称为 ItemAttributes 和命名空间http://ecs.amazonaws.com/doc/2011-08-01/的元素,并且其中至少有一个包含名称为 ProductGroup 的子元素位于同一命名空间中,并且文本内容Book