0

我正在尝试使用 XmlDocument() 逐个节点读取 XML 文件并输出每个元素。

经过多次反复试验,我确定在我的节点上具有 xmlns 属性会导致没有节点从 SelectNodes() 调用返回。不知道为什么。

由于我无法更改输出格式并且无法访问实际的命名空间,我有哪些选择来解决这个问题?

此外,我还有一些具有子节点的元素。在循环通过 XML 文件时如何访问这些?IE,我需要解密 CipherValue 元素,但不确定如何访问该节点?

下面的示例:

doc.Load(@"test.xml");
XmlNodeList logEntryNodeList = doc.SelectNodes("/Logs/LogEntry");
Console.WriteLine("Nodes = {0}", logEntryNodeList.Count);
foreach (XmlNode xn in logEntryNodeList)
{
    string dateTime = xn["DateTime"].InnerText;
    string sequence = xn["Sequence"].InnerText;
    string appId = xn["AppID"].InnerText;
    Console.WriteLine("{0}    {1} {2}", dateTime, sequence, appId);
}

示例 XML 如下所示:

<Logs>
<LogEntry Version="1.5" PackageVersion="10.10.0.10" xmlns="http://private.com">
  <DateTime>2013-02-04T14:05:42.912349-06:00</DateTime>
  <Sequence>5058</Sequence>
  <AppID>TEST123</AppID>
  <StatusDesc>
    <EncryptedData>
      <CipherData xmlns="http://www.w3.org/2001/04/xmlenc#">
        <CipherValue>---ENCRYPTED DATA BASE64---</CipherValue>
      </CipherData>
    </EncryptedData>
  </StatusDesc>
  <Severity>Detail</Severity>
</LogEntry>
<LogEntry Version="1.5" PackageVersion="10.10.0.10" xmlns="http://private.com">
  <DateTime>2013-02-04T14:05:42.912350-06:00</DateTime>
  <Sequence>5059</Sequence>
  <AppID>TEST123</AppID>
  <StatusDesc>
    <EncryptedData>
      <CipherData xmlns="http://www.w3.org/2001/04/xmlenc#">
        <CipherValue>---ENCRYPTED DATA BASE64---</CipherValue>
      </CipherData>
    </EncryptedData>
  </StatusDesc>
  <Severity>Detail</Severity>
</LogEntry>
</Logs>
4

2 回答 2

1

经过多次反复试验,我确定在我的节点上具有 xmlns 属性会导致没有节点从 SelectNodes() 调用返回。不知道为什么。

xmlns属性有效地更改了元素内的默认命名空间,包括该元素本身。所以你的LogEntry元素的命名空间是"http://private.com". 您需要在 XPath 查询中适当地包含它,可能通过XmlNamespaceManager.

(如果您可以改用 LINQ to XML,则可以轻松地使用命名空间。)

于 2013-02-06T16:56:29.840 回答
0

您可以使用 Linq to Xml(如 Jon 所述)。这是根据名称空间解析您的 xml 文件的代码。结果是匿名对象的强类型序列(即 Date 属性的类型为 DateTime,Sequence 为整数,AppID 为字符串):

XDocument xdoc = XDocument.Load("test.xml");
XNamespace ns = "http://private.com";
var entries = xdoc.Descendants("Logs")
                  .Elements(ns + "LogEntry")
                  .Select(e => new {
                      Date = (DateTime)e.Element(ns + "DateTime"),
                      Sequence = (int)e.Element(ns + "Sequence"),
                      AppID = (string)e.Element(ns + "AppID")
                  }).ToList();   

Console.WriteLine("Entries count = {0}", entries.Count);    

foreach (var entry in entries)
{
    Console.WriteLine("{0}\t{1} {2}", 
                      entry.Date, entry.Sequence, entry.AppID);
}
于 2013-02-06T17:07:29.563 回答