c# - 使用 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
解决方案
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();
}
}
}
推荐阅读
- r - 使用 rChart 包中的 nplot 时如何将标签添加到 x 轴
- angular - Angular 8:将表单标记为从父组件触摸
- flutter - sweepGradient 终点没有动画
- javascript - 我正在尝试在 electronjs 上打印页面,但是当我按照复制代码时它不会打印或给出任何错误
- c# - 使用 C# 从 Outlook 2016 电子邮件项目捕获或导入收件人、发件人、主题和电子邮件正文
- .net - 如何在特定应用程序上禁用 BrotliCompressionModule
- sql - 如何获取 PostgreSQL 表中的相关数据?
- javascript - 反应:Componentdidupdate,无法访问对象值
- r - 如何在 ggplot2 中为单个几何/颜色组合创建图例条目?
- google-apps-script - 谷歌表格脚本在最后一条记录之后复制并粘贴到另一张表格中