【问题标题】:Create Filtered XmlNodeList创建过滤的 XmlNodeList
【发布时间】:2013-01-12 13:29:54
【问题描述】:

我有包含图像信息的 XML 数据。我的第一个目标是创建过滤后的XmlNodeList(例如,返回color == yellow 所在的所有图像)。最终目标是能够返回color == yellow 的图像名称列表(返回整个过滤的XmlNodeList 很棒,但我真的只需要该过滤列表中的一个元素,例如名称或ID) .

在我的例子中,根节点称为Images,我希望能够在每个Image 节点中进行搜索。我的 XML 数据没有 XML 属性,因此每一位数据都表示为一个元素(使颜色“黄色”成为图像的子节点,而不是图像的属性)。

XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Images xmlns="http://oec.api.opsource.net/schemas/server"
    xmlns:ns9="http://oec.api.opsource.net/schemas/multigeo"
    xmlns:ns5="http://oec.api.opsource.net/schemas/vip"
    xmlns:ns12="http://oec.api.opsource.net/schemas/storage"
    xmlns:ns6="http://oec.api.opsource.net/schemas/whitelabel"
    xmlns:ns13="http://oec.api.opsource.net/schemas/manualimport"
    xmlns:ns7="http://oec.api.opsource.net/schemas/datacenter"
    xmlns:ns10="http://oec.api.opsource.net/schemas/reset"
    xmlns:ns8="http://oec.api.opsource.net/schemas/general"
    xmlns:ns11="http://oec.api.opsource.net/schemas/support"
    xmlns:ns2="http://oec.api.opsource.net/schemas/directory"
    xmlns:ns4="http://oec.api.opsource.net/schemas/network"
    xmlns:ns3="http://oec.api.opsource.net/schemas/organization">
    <Image>
        <id>mcd93jf8dd</id>
        <name>cat</name>
        <color>yellow</color>
    </Image>
    <Image>
        <id>d4b8l23sas</id>
        <name>dog</name>
        <color>yellow</color>
    </Image>
</Images>

我最初的 XML 数据源是一个流。我已经找到了使用 foreach 循环遍历我的 XML 层次结构的不同级别的方法,但是我一直遇到在子节点上没有我需要的所有方法可用的问题。其他地方的建议似乎建议使用XPath 来实现我的过滤器,但我无法让它与我目前所拥有的一起工作:

C#

//'stream' previously defined as a Stream
XmlReader reader = XmlReader.Create(stream);
XmlDocument xml = new XmlDocument();
xml.Load(reader);
XmlElement root = xml.DocumentElement;
XmlNodeList images = root.ChildNodes;

foreach (XmlNode image in images) {

    XmlNodeList attributes = image.ChildNodes;

    foreach (XmlNode attribute in attributes) {
        //do stuff
    }

}

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    我在这里发布了一些代码:http://ideone.com/jRFoBW 来演示以下技术。 XML 是从流加载还是直接从字符串加载应该没有区别,但我已将其设置为从流加载以尽可能模拟您的条件。

    由于您的 XML 使用命名空间,因此您需要创建命名空间管理器并将命名空间添加到其中:

    XmlNamespaceManager nsm = new XmlNamespaceManager(xml.NameTable);
    // The prefix can be anything as long as you use it consistently
    nsm.AddNamespace("i", "http://oec.api.opsource.net/schemas/server");
    

    然后您可以执行以下操作以获取黄色ids 和names 的列表:

    XmlNodeList ids = xml.SelectNodes("/i:Images/i:Image[i:color = 'yellow']/i:id", nsm);
    XmlNodeList names = xml.SelectNodes("/i:Images/i:Image[i:color = 'yellow']/i:name", nsm);
    

    虽然如果你想要 idname 黄色图像,我建议这样做:

    foreach(XmlNode yellowImage in xml.SelectNodes("/i:Images/i:Image[i:color = 'yellow']", nsm))
    {
       string id = yellowImage.SelectSingleNode("i:id", nsm).InnerText;
       string name = yellowImage.SelectSingleNode("i:name", nsm).InnerText;
    
       // use id and name
    }
    

    【讨论】:

    • 代码可以编译,但是当我测试它时,我没有得到任何结果。使用第一种方法,当我执行 ids.Count 时,它返回 0。当我执行 foreach 循环并在循环中添加 Console.Writeline(id) 时,没有输出。
    • 鉴于输入 XML,我希望它能够工作。您能否检查xml.OuterXml 的值以确保它与上面的XML 相同?也许有一个命名空间声明?
    • 我使用的实际 XML 数据确实包含 XML 声明和命名空间。正如您所建议的那样,如果这有影响,我将不得不进一步调查。
    • 您能否将实际的根标签(我假设它是&lt;Images&gt; 标签)与其所有命名空间声明共享?
    • 创建命名空间管理器仍然给我留下了相同的结果。代码编译,但我得到没有元素的 XmlNodeLists。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-06
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    相关资源
    最近更新 更多