代码之家  ›  专栏  ›  技术社区  ›  Mat Nadrofsky

使用C_在XML文档中查找特定值的好方法是什么?

  •  6
  • Mat Nadrofsky  · 技术社区  · 16 年前

    我正在调用Oracle公开的WebService,它接受itemID的输入并返回相应的item号。我想从响应中包含的XML中获取已返回的项目编号。

    XML如下所示:

    <env:Envelope
      xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:ns0="http://dev1/MyWebService1.wsdl">
     <env:Header>
      <wsse:Security
        xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
        xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
        xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
        env:mustUnderstand="1"/>
     </env:Header>
     <env:Body>
      <ns0:getItemNbrByItemIdResponseElement>
       <ns0:result>1010603</ns0:result>
      </ns0:getItemNbrByItemIdResponseElement>
     </env:Body>
    </env:Envelope>
    

    我只想抓住 <ns0:result>1010603</ns0:result> 尤其是1010603。

    到目前为止,我还没有用C做过大量的XML解析工作,我还使用了一些不同的方法。推荐的方法是什么?

    我在VS2008上(所以可以使用xpath等)

    6 回复  |  直到 16 年前
        1
  •  15
  •   Jon Skeet    16 年前

    我个人会使用linq-to-xml,因为我发现它比xpath更容易处理,特别是在涉及名称空间时。你会做如下的事情:

    XNamespace ns0 = "http://dev1/MyWebService1.wsdl";
    
    String result = doc.Descendants(ns0 + "result").First().Value;
    

    注意 doc 这里应该是一个 XDocument , XmlDocument . (我想这就是为什么它没有出现在你面前。)

        2
  •  5
  •   annakata    16 年前

    fwiw您可以用这样的xpath来欺骗名称空间问题: //*[local-name()='result']

        3
  •  3
  •   Dirk Vollmar    16 年前

    如果不想使用linq,可以使用xpathdocument检索值:

    XPathDocument xmldoc = new XPathDocument(@"C:\tmp\sample.xml");
    XPathNavigator nav = xmldoc.CreateNavigator();
    
    XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable);
    nsMgr.AddNamespace("ns0", "http://dev1/MyWebService1.wsdl");
    
    XPathNavigator result = nav.SelectSingleNode("//ns0:result", nsMgr);
    System.Diagnostics.Debug.WriteLine(result.Value);
    

    xpathdocument具有较低的内存占用,在您的场景中,它最有可能比xmldocument更快。XML文档在内存中构建XML文档的完整对象模型,而XpathDocument不这样做。

        4
  •  2
  •   Pete OHanlon    16 年前

    从我的头顶上看,应该可以做到以下几点:

    XmlDocument doc = new XmlDocument();
    doc.PreserveWhitespace = true;
    
    XmlNamespaceManager mgr = GetNamespace(doc);
    doc.LoadXml(xmltext);
    
    XmlNode nd = doc.DocumentElement.SelectSingleNode("//ns0:result", mgr);
    

    命名空间代码如下所示:

    private XmlNamespaceManager GetNamespace(XmlDocument document)
    {
        XmlNamespaceManager mgr = new XmlNamespaceManager(document.NameTable);
        mgr.AddNamespace("ns0", "http://dev1/MyWebService1.wsdl");
        return mgr;
    }
    

    您需要使用名称空间管理器,因为XML文档有与其关联的名称空间,而xpath在查询解析中使用它。

        5
  •  1
  •   Mat Nadrofsky    16 年前

    为了解决这个问题,我使用了乔恩·斯基特的答案。这是我必须实现的代码,以使这项工作(为任何其他人的未来利益)。

    XmlDocument xmlDoc = new XmlDocument();
    
    XNamespace ns0 = "http://dev1/MyWebService1.wsdl";
    
    xmlDoc.Load(request.GetResponse().GetResponseStream());
    
    XDocument xDoc = XDocument.Load(new XmlNodeReader(xmlDoc));                          
    
    String result = xDoc.Descendants(ns0 + "result").First().Value;
    

    当然,这假设我从一个名为 请求 .

        6
  •  0
  •   Dimitre Novatchev    16 年前

    这个问题有非常好和完整的答案。

    我会添加 只是出于好奇,一个非常简单的xpath表达式可以完成这项工作 在这种特殊情况下:

    normalize-space(/)

    这在C中很容易做到,使用如下两行:

            XPathNavigator navigator = document.CreateNavigator();
    
            string res = (string)navigator.Evaluate("normalize-space(/)");
    

    随着.NET XPath引擎的良好优化,它的评估甚至可能是有效的。