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

时间:2008-12-17 14:42:09

标签: c# xml xpath searching-xml

我正在调用Oracle公开的WebService,它接受ItemID的输入并返回相应的Item Number。我想获取已从响应中包含的XML返回的Item Number。

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 个答案:

答案 0 :(得分:15)

我个人使用LINQ to XML,因为我发现比XPath更容易处理,特别是涉及名称空间时。你会做类似的事情:

XNamespace ns0 = "http://dev1/MyWebService1.wsdl";

String result = doc.Descendants(ns0 + "result").First().Value;

请注意,doc此处应为XDocument XmlDocument。 (我的猜测是,这就是为什么它没有出现在你面前。)

答案 1 :(得分:5)

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

答案 2 :(得分:3)

如果您不想使用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更快。 XmlDocument在内存中构建XML文档的完整对象模型,而XPathDocument不这样做。

答案 3 :(得分:2)

在我的头顶,以下应该有效:

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在查询解析中使用它。

答案 4 :(得分:1)

为了解决这个问题,我使用了Jon Skeet的答案。这是我必须实现的代码才能实现这一目标(为了其他人未来的利益)。

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;

这当然假设我从名为请求的HttpWebRequest获取我的回复。

答案 5 :(得分:0)

这个问题有很好的答案。

我只是出于好奇而添加,在这种特殊情况下,一个极其简单的XPath表达式可以完成这项工作

normalize-space(/)

使用类似下面两行的内容很容易在C#中完成:

        XPathNavigator navigator = document.CreateNavigator();

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

通过.NET XPath引擎的良好优化,其评估甚至可能是高效的。