使用xpath选择如何在示例中获取此元素的值?

时间:2015-02-25 06:59:12

标签: c# xml xpath

使用此XML

<?xml version="1.0" encoding="UTF-8"?>
<createTransactionResponse xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <refId>999999999</refId>
   <messages>
      <resultCode>Ok</resultCode>
      <message>
         <code>I00001</code>
         <text>Successful.</text>
      </message>
   </messages>
   <transactionResponse>
      <responseCode>1</responseCode>
      <authCode>HH1D69</authCode>
      <avsResultCode>Y</avsResultCode>
      <cvvResultCode>P</cvvResultCode>
      <cavvResultCode>2</cavvResultCode>
      <transId>2228993425</transId>
      <refTransID />
      <transHash>916EE7527B17B62F62AA72B4C71F8322</transHash>
      <testRequest>0</testRequest>
      <accountNumber>XXXX0015</accountNumber>
      <accountType>MasterCard</accountType>
      <messages>
         <message>
            <code>1</code>
            <description>This transaction has been approved.</description>
         </message>
      </messages>
      <userFields>
         <userField>
            <name>MerchantDefinedFieldName1</name>
            <value>MerchantDefinedFieldValue1</value>
         </userField>
         <userField>
            <name>favorite_color</name>
            <value>blue</value>
         </userField>
      </userFields>
   </transactionResponse>
</createTransactionResponse>

我想从这里获得&#34; resultCode&#34;,

<messages><resultCode>Ok</resultCode><message>

但我使用的xpath没有给我resultCode的值Ok。

我做错了什么?

-

static void Main(string[] args)
    {

                    string myXML = @"<?xml version=""1.0"" encoding=""utf-8""?><createTransactionResponse xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""AnetApi/xml/v1/schema/AnetApiSchema.xsd""><refId>999999999</refId><messages><resultCode>Ok</resultCode><message><code>I00001</code><text>Successful.</text></message></messages><transactionResponse><responseCode>1</responseCode><authCode>HH1D69</authCode><avsResultCode>Y</avsResultCode><cvvResultCode>P</cvvResultCode><cavvResultCode>2</cavvResultCode><transId>2228993425</transId><refTransID /><transHash>916EE7527B17B62F62AA72B4C71F8322</transHash><testRequest>0</testRequest><accountNumber>XXXX0015</accountNumber><accountType>MasterCard</accountType><messages><message><code>1</code><description>This transaction has been approved.</description></message></messages><userFields><userField><name>MerchantDefinedFieldName1</name><value>MerchantDefinedFieldValue1</value></userField><userField><name>favorite_color</name><value>blue</value></userField></userFields></transactionResponse></createTransactionResponse>";




 string myValue = XMLSelect(myXML, "createTransactionResponse/messages/message/resultCode");
        //myValue should = "Ok" but it does not :(

    }

    public static string XMLSelect(string _xmldoc, string _xpath)
    {
        string returnedValue = string.Empty;
        XmlDocument doc = new XmlDocument();

        try
        {
            doc.LoadXml(_xmldoc);

            XmlElement root = doc.DocumentElement;
            returnedValue = (string)doc.SelectNodes(_xpath)[0].InnerText; 
        }
        catch (Exception ex)
        {
            return "";
        }
        return returnedValue;
    }

1 个答案:

答案 0 :(得分:1)

您的第一个问题是您最初提供的XML无效。当您遇到异常时,您可以通过返回""屏蔽它,因此您不再拥有任何信息。

所以做IMO的第一件事就是删除虚假的异常处理:

public static string XMLSelect(string _xmldoc, string _xpath)
{
    string returnedValue = string.Empty;
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(_xmldoc);        
    XmlElement root = doc.DocumentElement;
    return (string)doc.SelectNodes(_xpath)[0].InnerText; 
}

现在,XPath的问题在于XML中的所有元素都在AnetApi/xml/v1/schema/AnetApiSchema.xsd的命名空间中 - 所以您可能需要XmlNamespaceManager。考虑到您从XPath中分割负载的方式,将这种方法正确分离是有点棘手的,但目前您可以为正确的命名空间引入别名ns

接下来,您的XPath不正确,因为当这两个元素是对等元素时,它会查找message/resultCode。你不想要message部分。

这是一个简短但完整的程序,可以解决所有这些问题:

using System;
using System.Xml;

public class Program
{
    static void Main(string[] args)
    {
        // As per the question
        string myXML = "...";
        string myValue = XMLSelect(myXML, "ns:createTransactionResponse/ns:messages/ns:resultCode");
        Console.WriteLine(myValue);
    }

    public static string XMLSelect(string _xmldoc, string _xpath)
    {
        string returnedValue = string.Empty;
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(_xmldoc);        
        var nsm = new XmlNamespaceManager(doc.NameTable);
        nsm.AddNamespace("ns", "AnetApi/xml/v1/schema/AnetApiSchema.xsd");
        XmlElement root = doc.DocumentElement;
        return (string)doc.SelectNodes(_xpath, nsm)[0].InnerText;
    }
}

如果您可以使用LINQ to XML,而只是处理文档而不是传入XML文本和XPath选择器,那么它会更简单:

XDocument doc = XDocument.Parse(xml);
XNamespace ns = "AnetApi/xml/v1/schema/AnetApiSchema.xsd";
string code = (string) doc.Root
                          .Element(ns + "messages")
                          .Element(ns + "resultCode");
Console.WriteLine(code);