【问题标题】:parsing an xmldocument from a webrequest从 webrequest 解析 xmldocument
【发布时间】:2013-07-31 16:05:48
【问题描述】:

解析这个布局我花了不少时间:

<string xmlns="http://www.namespaceuri.com/Admin/ws">
    <CardTrxSummary> 
        <PaymentMethod> 
            <Payment_Type_ID>VISA </Payment_Type_ID> 
            <Authorization>0.0000</Authorization> 
            <Capture>0.0000</Capture> <ForceCapture>0.0000</ForceCapture> 
            <PostAuth>0.0000</PostAuth> <Return>0.0000</Return> 
            <Sale>3419.2700</Sale> <Receipt>0.0000</Receipt> 
            <RepeatSale>0.0000</RepeatSale> 
            <Activate>0.0000</Activate> 
            <Deactivate>0.0000</Deactivate> 
            <Reload>0.0000</Reload> 
            <Authorization_Cnt>0</Authorization_Cnt> 
            <Capture_Cnt>0</Capture_Cnt> 
            <ForceCapture_Cnt>0</ForceCapture_Cnt> 
            <PostAuth_Cnt>0</PostAuth_Cnt> 
            <Return_Cnt>0</Return_Cnt> 
            <Sale_Cnt>13</Sale_Cnt> 
            <Receipt_Cnt>0</Receipt_Cnt> 
            <RepeatSale_Cnt>0</RepeatSale_Cnt> 
            <Activate_Cnt>0</Activate_Cnt> 
            <Deactivate_Cnt>0</Deactivate_Cnt> 
            <Reload_Cnt>0</Reload_Cnt> 
            <Cnt>13</Cnt> 
        </PaymentMethod> 
    </CardTrxSummary>
</string>

我正在尝试使用此代码来获得特定结果:

private static string ReadValueFromXml(XmlDocument xmlDocument, string field)
{
  var xdoc = xmlDocument.ToXDocument();
  var ns = "http://www.namespaceuri.com/Admin/ws";
  return xdoc.Descendants(ns + "PaymentMethod")
             .Select(x => (string) x.Attribute("Cnt"))
             .FirstOrDefault();
}

此时,它给了我这样的信息:

':' 字符,十六进制值 0x3A,不能包含在 名字。

我是这样尝试的:

  XmlNodeList xnList = xmlDocument.SelectNodes("/CardTrxSummary/PaymentMethod");
  foreach (XmlNode xn in xnList)
  {
    Console.WriteLine("Sale: " + xn["Sale"].InnerText);
    Console.WriteLine("Sale_Cnt: " + xn["Sale_Cnt"].InnerText);
    Console.WriteLine("Payment_Type_ID: " + xn["Payment_Type_ID"].InnerText);
  }

而且它从未进入 foreach。

如何获取 PaymentMethod 中的值?

编辑

我查看了 xmldocument 的内部文本,它是这样显示的:

"<?xml version=\"1.0\" encoding=\"utf-8\"?><string xmlns=\"http://www.namespaceuri.com/Admin/ws\">&lt;CardTrxSummary&gt;\r\n  &lt;PaymentMethod&gt;\r\n    &lt;Payment_Type_ID&gt;VISA      &lt;/Payment_Type_ID&gt;\r\n    &lt;Authorization&gt;0.0000&lt;/Authorization&gt;\r\n    &lt;Capture&gt;0.0000&lt;/Capture&gt;\r\n    &lt;ForceCapture&gt;0.0000&lt;/ForceCapture&gt;\r\n    &lt;PostAuth&gt;0.0000&lt;/PostAuth&gt;\r\n    &lt;Return&gt;0.0000&lt;/Return&gt;\r\n    &lt;Sale&gt;3419.2700&lt;/Sale&gt;\r\n    &lt;Receipt&gt;0.0000&lt;/Receipt&gt;\r\n    &lt;RepeatSale&gt;0.0000&lt;/RepeatSale&gt;\r\n    &lt;Activate&gt;0.0000&lt;/Activate&gt;\r\n    &lt;Deactivate&gt;0.0000&lt;/Deactivate&gt;\r\n    &lt;Reload&gt;0.0000&lt;/Reload&gt;\r\n    &lt;Authorization_Cnt&gt;0&lt;/Authorization_Cnt&gt;\r\n    &lt;Capture_Cnt&gt;0&lt;/Capture_Cnt&gt;\r\n    &lt;ForceCapture_Cnt&gt;0&lt;/ForceCapture_Cnt&gt;\r\n    &lt;PostAuth_Cnt&gt;0&lt;/PostAuth_Cnt&gt;\r\n    &lt;Return_Cnt&gt;0&lt;/Return_Cnt&gt;\r\n    &lt;Sale_Cnt&gt;13&lt;/Sale_Cnt&gt;\r\n    &lt;Receipt_Cnt&gt;0&lt;/Receipt_Cnt&gt;\r\n    &lt;RepeatSale_Cnt&gt;0&lt;/RepeatSale_Cnt&gt;\r\n    &lt;Activate_Cnt&gt;0&lt;/Activate_Cnt&gt;\r\n    &lt;Deactivate_Cnt&gt;0&lt;/Deactivate_Cnt&gt;\r\n    &lt;Reload_Cnt&gt;0&lt;/Reload_Cnt&gt;\r\n    &lt;Cnt&gt;13&lt;/Cnt&gt;\r\n  &lt;/PaymentMethod&gt;\r\n&lt;/CardTrxSummary&gt;</string>"

我认为这是我的问题的一部分?

编辑#2

这就是我最终要让它发挥作用的方法。我确信有更好的方法:

  var tst2 = tst.InnerText.Replace("&lt;", "<").Replace("&gt;", ">").Replace("\r\n", string.Empty);
  Console.WriteLine("Cnt: " + ReadXmlValue1(tst2, "Cnt"));

以及我的解析方法:

private static void ReadXmlValue1(string xmlDocument)
{
  XDocument xdoc = XDocument.Parse(xmlDocument);
  //XNamespace ns = "http://www.namespaceuri.com/Admin/ws";
  var payments = from p in xdoc.Descendants("PaymentMethod")
                 select new
                 {
                   Sale = (decimal)p.Element("Sale"),
                   SaleCount = (int)p.Element("Sale_Cnt"),
                   PaymentType = (string)p.Element("Payment_Type_ID")
                 };
  Console.WriteLine("Count: " + payments.Count());
  foreach (var payment in payments)
  {
    Console.WriteLine("Sale: " + payment.Sale);
    Console.WriteLine("Sale_Cnt: " + payment.SaleCount);
    Console.WriteLine("Payment_Type_ID: " + payment.PaymentType);
  }

}

编辑#3

这就是我创建 xmldocument 的方式:

/// <summary>
///  Get Data in xml format by url
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private static XmlDocument GetXmlDataFromUrl(string url)
{
  //requesting the particular web page
  var httpRequest = (HttpWebRequest)WebRequest.Create(url);

  //geting the response from the request url
  var response = (HttpWebResponse)httpRequest.GetResponse();

  //create a stream to hold the contents of the response (in this case it is the contents of the XML file
  var receiveStream = response.GetResponseStream();

  //creating XML document
  var mySourceDoc = new XmlDocument();

  //load the file from the stream
  if (receiveStream != null)
  {
    mySourceDoc.Load(receiveStream);

    //close the stream
    receiveStream.Close();
    return mySourceDoc;
  }
  return null;
}

【问题讨论】:

  • 试试不带命名空间的XDocument 版本 (xdoc.Descendants("PaymentMethod"))。我认为您还需要更改您的选择,因为没有一个元素具有名为 cnt 的属性。
  • 我会改变它,看看会发生什么,但这个确实存在:13你指的是案例吗?
  • Cnt 是该元素的名称,而不是属性。

标签: c# xml linq xmldocument


【解决方案1】:

您可以使用LINQ to XML 获取强类型匿名支付对象列表:

WebClient client = new WebClient();
string content = client.DownloadString(url);

XDocument xdoc = XDocument.Parse(content);
XNamespace ns = "http://www.namespaceuri.com/Admin/ws";
var payments = from p in xdoc.Descendants(ns + "PaymentMethod")
                select new {
                    Sale = (decimal)p.Element(ns + "Sale"),
                    SaleCount = (int)p.Element(ns + "Sale_Cnt"),
                    PaymentType = (string)p.Element(ns + "Payment_Type_ID")
                };

请记住,您的 xml 已声明命名空间,因此您应该在指定元素名称时提供它。

用法:

foreach(var payment in payments)
{
   Console.WriteLine("Sale: " + payment.Sale);
   Console.WriteLine("Sale_Cnt: " + payment.SaleCount);
   Console.WriteLine("Payment_Type_ID: " + payment.PaymentType);
}

【讨论】:

  • 我试过了,payments.count 为 0。我对此没有任何反应。
  • @ErocM 如果您正在解析 xml 字符串,则使用 XDocument.Parse(xml) 方法创建文档。否则请确保您正在加载正确的文件。
  • 我最终使用了这个,但我确信有更好的方法。请参阅我的第二次编辑。你能检查一下并告诉我是否有更好的方法吗?
  • @ErocM 你如何创建tstXmlDocument?
  • 我赞成你帮助我。午饭回来后,我将插入代码。 Tyvm 的帮助!
【解决方案2】:
XmlNode node = xmlDocument.SelectSingleNode("/string/CardTrxSummary/PaymentMethod");
Console.WriteLine("Sale: " + node.SelectSingleNode("Sale").InnerText);
Console.WriteLine("Sale_Cnt: " + node.SelectSingleNode("Sale_Cnt").InnerText);
Console.WriteLine("Payment_Type_ID: " + node.SelectSingleNode("Payment_Type_ID").InnerText);

或者您可以使用 getElementByTagName 代替;

Console.WriteLine("Sale: " + xmlDocument.getElementByTagName("Sale").InnerText);
Console.WriteLine("Sale_Cnt: " + xmlDocument.getElementByTagName("Sale_Cnt").InnerText);
Console.WriteLine("Payment_Type_ID: " + xmlDocument.getElementByTagName("Payment_Type_ID").InnerText);

请注意,上面的2个方法是假设标签永远不会返回null。

如果你想处理可能的空节点,你可以这样做。

string text = xmlDocument.getElementByTagName("Sale") != null ? xmlDocument.getElementByTagName("Sale").InnerText : "unidentified";

上面一行的格式如下:

var variable = condition ? A : B;

基本上就是说如果条件为真,变量等于A,否则变量等于B。

【讨论】:

  • 我将代码完全按原样插入到它自己的方法中,然后我得到“对象引用未设置为对象的实例”。节点为空。
  • 表示您要查找的节点不存在,因此为空。你在哪一行得到错误?
  • 抱歉,有错字,我刚刚改正了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-07
  • 2010-11-23
  • 2020-06-09
  • 1970-01-01
相关资源
最近更新 更多