首页 > 解决方案 > 使用 XPath 将 XML 解析为 CSV。创建外循环还是正确的方法?

问题描述

我正在检索 http\xml 响应并解析以输出 csv 文件。如果只有一个响应,我可以这样做,但是当每个节点超过 1 个时,它会解析所有同名的第一个节点,然后解析所有同名的第二个节点等,而不是节点 1、节点 2、节点 1、节点 2。有是丑陋的,我相信可以写得更好。我的简单请求是如何围绕它放置一个循环,这样它一次只返回一组数据,或者我应该将所有的 forEachs 组合起来,因为 xpaths 为每个循环获取值语句?或者我应该使用不同的技术,如 XMLReader 或其他东西?XML 文件

<?xml version="1.0" encoding="UTF-8" ?>
<multistatus xmlns="DAV:">
 <response>
  <href>http://192.168.0.2:80/User-84</href>
  <propstat>
    <prop>
        <handle>
            <dsref handle="User-84"><displayname>George Thurogood</displayname>
                <firstname>George</firstname>
                <lastname>Thurogood</lastname>
                <username>cz001234</username>
             </dsref>
         </handle>
         <email>george@lab.local</email>
         <isActive>1</isActive>
         <domain>Lab.local</domain>
     </prop>
     <status>HTTP/1.1 200 OK</status>
 </propstat>
 <propstat>
    <prop>
        <firstname/>
        <lastname/>
     </prop>
     <status>HTTP/1.1 404 Not Found</status>
 </propstat>
</response>
<response>
<href>http://192.168.0.2:80/User-83</href>
<propstat>
    <prop>
        <handle>
            <dsref handle="User-83">
                <displayname>Molly Meldrum</displayname>
                <firstname>Molly</firstname>
                <lastname>Meldrum</lastname>
                <username>cz026381</username>
            </dsref>
        </handle>
        <email>molly@lab.local</email>
        <isActive>1</isActive>
        <domain>Lab.local</domain>
    </prop>
    <status>HTTP/1.1 200 OK</status>
</propstat>
<propstat>
    <prop>
        <firstname/>
        <lastname/>
    </prop>
    <status>HTTP/1.1 404 Not Found</status>
</propstat>

我目前使用的代码

if (response.StatusCode == HttpStatusCode.OK)
            {

            }
            response.Close();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(responseString);P
            responseString = "";

            //create the namespace manager
            var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
            nsmgr.AddNamespace("DAV", "DAV:");
            XmlNodeList elemList = xmlDoc.SelectNodes("//DAV:prop", nsmgr);



              foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:prop/DAV:handle/DAV:dsref", nsmgr))
              {
                strNode = node.Attributes["handle"].Value;
                strFNnode = 
                //strNode = strNode + " - " + node.InnerText;
                //responseString += strNode + " , " + "\r\n";            
              }

              foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:prop/DAV:handle/DAV:dsref/DAV:displayname", nsmgr))
              {
                //strNode = node.Attributes["handle"].Value;
                strNode = strNode + "," + node.InnerText;
                //responseString += strNode + " ,  " + "\r\n";                    
              }
              foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:prop/DAV:handle/DAV:dsref/DAV:firstname", nsmgr))
              {
                //strNode = node.Attributes["handle"].Value;
                   strNode = strNode + "," + node.InnerText;
                // responseString += strNode + " ,  " + "\r\n";
              }
              foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:prop/DAV:handle/DAV:dsref/DAV:lastname", nsmgr))
              {
                //strNode = node.Attributes["handle"].Value;
                strNode = strNode + "," + node.InnerText;
                // responseString += strNode + " ,  " + "\r\n";
              }
              foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:prop/DAV:handle/DAV:dsref/DAV:username", nsmgr))
              {
                //strNode = node.Attributes["handle"].Value;
                  strNode = strNode + "," + node.InnerText;
                // responseString += strNode + " ,  " + "\r\n";
              }
              foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:prop/DAV:email", nsmgr))
              {
                //strNode = node.Attributes["handle"].Value;
                strNode = strNode + "," + node.InnerText;
                // responseString += strNode + " ,  " + "\r\n";
              }
              foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:prop/DAV:isActive", nsmgr))
              {
                //strNode = node.Attributes["handle"].Value;
                strNode = strNode + "," + node.InnerText;
                // responseString += strNode + "," + "\r\n";
              }
              foreach (XmlNode node in xmlDoc.SelectNodes("//DAV:prop/DAV:domain", nsmgr))
              {
                //strNode = node.Attributes["handle"].Value;
                strNode = strNode + "," + node.InnerText;
                responseString += strNode + "\r\n";
              }

            return temp;

这应该返回

User-84,George Thurogood,George,Thurogood,cz001234,george@lab.local,1,lab.local
User-83,Molly Meldrun,Molly,Meldrum,cz026381,Molly@lab.local,1,lab.local

标签: c#xpathxml-parsing

解决方案


Try xml linq :

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;


namespace ConsoleApplication100
{
    class Program
    {
        const string XML_FILENAME = @"c:\temp\test.xml";
        const string CSV_FILENAME = @"c:\temp\test.csv";
        static void Main(string[] args)
        {
            PropStat.ParseXML(XML_FILENAME);
            PropStat.CreateCSV(CSV_FILENAME);
        }


    }
    public class PropStat
    {
        public static List<PropStat> propStats = new List<PropStat>();

        public string href { get; set; }
        public string handle { get; set; }
        public string firstname { get; set; }
        public string lastname { get; set; }
        public string username { get; set; }
        public string email { get; set; }
        public Boolean?  isactive { get; set; }
        public string domain { get; set; }
        public string status { get; set; }

        public static void ParseXML(string filename)
        {
            XDocument doc = XDocument.Load(filename);
            XElement root = doc.Root;
            XNamespace ns = root.GetDefaultNamespace();

            foreach (XElement response in doc.Descendants(ns + "response"))
            {
                string href = (string)response.Element(ns + "href");

                foreach(XElement propstat in response.Descendants(ns + "propstat"))
                {
                    PropStat newPropStat = new PropStat();
                    propStats.Add(newPropStat);
                    newPropStat.href = href;

                    XElement dsref = propstat.Descendants(ns + "dsref").FirstOrDefault();

                    if (dsref != null)
                    {
                        newPropStat.handle = (string)dsref.Attribute("handle");
                    }

                    newPropStat.firstname = (string)propstat.Descendants(ns + "firstname").FirstOrDefault();
                    newPropStat.lastname = (string)propstat.Descendants(ns + "lastname").FirstOrDefault();
                    newPropStat.username = (string)propstat.Descendants(ns + "username").FirstOrDefault();
                    newPropStat.email = (string)propstat.Descendants(ns + "email").FirstOrDefault();
                    newPropStat.isactive = (string)propstat.Descendants(ns + "isactive").FirstOrDefault() == "0" ? false : true;
                    newPropStat.domain = (string)propstat.Descendants(ns + "domain").FirstOrDefault();
                    newPropStat.status = (string)propstat.Descendants(ns + "status").FirstOrDefault();
                }

            }
        }
        public static void CreateCSV(string filename)
        {
            StreamWriter writer = new StreamWriter(filename);
            string header = string.Join(",",
                "href",
                "handle",
                "firstname",
                "lastname",
                "username",
                "email",
                "isactive",
                "domain",
                "status");

            writer.WriteLine(header);


            foreach (PropStat propstat in propStats)
            {
                string data = string.Join(",",
                    propstat.href,
                    propstat.handle,
                    propstat.firstname,
                    propstat.lastname,
                    propstat.username,
                    propstat.email,
                    propstat.isactive,
                    propstat.domain,
                    propstat.status);

                writer.WriteLine(data);
            }
            writer.Flush();
            writer.Close();
        }
    }



}

推荐阅读