通过List从XML获取InnerText

问题描述 投票:2回答:2

我从服务中收到以下字符串作为列表

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<entry>
<id>1</id>
<title>Job 1</title>
<author>
<name>Jim James</name>
</author>
<modified>2018-08-10T14:50:46-04:00</modified>
</entry>
<entry>
<id>2</id>
<title>Job 2</title>
<author>
<name>John Smith</name>
</author>
<modified>2018-09-10T14:50:46-04:00</modified>
</entry>
<entry>
<id>3</id>
<title>Job 3</title>
<author>
<name>Paul Rain</name>
</author>
<modified>2018-06-10T14:50:46-04:00</modified>
</entry>
<entry>
<id>4</id>
<title>Job 4</title>
<author>
<name>Jim James</name>
</author>
<modified>2018-08-10T14:50:46-04:00</modified>
</entry>
</feed>

我试图通过内部文本获取名称的值,但无法这样做:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(response); //assuming response is above xml string
XmlNodeList parentNode = xmlDoc.GetElementsByTagName("entry");
foreach (XmlNode childrenNode2 in parentNode)
{
    var b = childrenNode2.SelectSingleNode("name").InnerText ?? string.Empty;
}

相反,我得到的对象是null异常。

 "ExceptionMessage": "Object reference not set to an instance of an object.",

任何指针赞赏。

c# asp.net .net xml xmldoc
2个回答
1
投票

你有一些问题:

  1. 您正在使用旧的XmlDocument API,它对名称空间的处理有些不方便。特别: XmlNode.GetElementsByTagName(string)是名称空间 - 不知道。它匹配“原始”限定元素名称,可能包括前缀。 在这种方法中,微软在documentation写道 注意 建议您使用XmlNode.SelectNodesXmlNode.SelectSingleNode方法而不是GetElementsByTagName方法。 相反,XmlNode.SelectSingleNode(string)是名称空间感知的,只选择空名称空间中的元素。 来自docs: 如果XPath表达式不包含前缀,则假定名称空间URI是空名称空间。如果您的XML包含默认命名空间,您仍然必须使用XmlNamespaceManager并为其添加前缀和命名空间URI;否则,您将无法获得所选节点。 这两种方法之间的这种不一致性解释了为什么您的代码部分工作,因为XML文档中的所有元素都属于http://purl.org/atom/ns#命名空间。
  2. 如果缩进XML,很明显<name>节点嵌套在容器<author>节点中: <feed version="0.3" xmlns="http://purl.org/atom/ns#"> <entry> <id>1</id> <title>Job 1</title> <author> <name>Jim James</name> </author> <modified>2018-08-10T14:50:46-04:00</modified> </entry> <!--Other entries omitted --> </feed> 您对SelectSingleNode("name")的调用也因为这个介入元素的存在而失败。

因此,以下代码将正常工作并正确选择您的条目名称:

var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(response); //assuming response is above xml string

var manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace("atom", @"http://purl.org/atom/ns#");

var parentNode = xmlDoc.DocumentElement.SelectNodes("./atom:entry", manager);
foreach (XmlNode childrenNode2 in parentNode)
{
    var name = childrenNode2.SelectSingleNode("./atom:author/atom:name", manager)?.InnerText ?? "";
    Console.WriteLine(name);
}           

样品小提琴#1 here

顺便说一句,使用LINQ to XML API可以更方便地完成这一切,完全避免使用XmlNamespaceManager和XPath等等:

var xmlDoc = XDocument.Parse(response);

var ns = (XNamespace)@"http://purl.org/atom/ns#";
foreach (var element in xmlDoc.Root.Elements(ns + "entry"))
{
    var name = element.Element(ns + "author")?.Element(ns + "name")?.Value ?? "";
    Console.WriteLine(name);
}           

样品小提琴#2 here


0
投票

给出的示例不是有效的XML:

  • 它没有文档元素
  • 它没有XML声明
  • 它包含未封闭的开放元素<author>

由于上述任何原因,我不希望这个解析。

然而,NullReferenceException没有正确地传达失败的原因,所以这里可能还有其他东西。使用调试器确定引发此异常的行。

假设您错过了一些XML并且它实际上是有效的,这也可能是由于未指定您要选择的元素的命名空间引起的。如果文档具有目标名称空间http://some-namespace,则entry不是要选择的正确名称;您必须包含命名空间。 GetElementsByTagName有一个overload with two arguments,其中第二个是命名空间。

© www.soinside.com 2019 - 2024. All rights reserved.