通过 List 从 XML 获取 InnerText
Get InnerText from XML via List
我从服务收到以下字符串列表
<?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>
我试图通过内部文本获取 name 的值,但无法这样做:
即
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;
}
相反,我得到的是 object is null 异常。
"ExceptionMessage": "Object reference not set to an instance of an object.",
感谢任何指点。
给定的样本无效XML:
- 它没有文档元素
- 它没有 XML 声明
- 它包含未闭合的打开元素
<author>
由于这些原因中的任何一个,我不希望它被解析。
然而,NullReferenceException 没有正确传达失败的原因,因此这里可能还有其他原因。使用您的调试器确定哪一行抛出此异常。
假设您遗漏了一些 XML 而它实际上是有效的,这也可能是由于未指定您打算 select 的元素的名称空间造成的。如果文档具有目标命名空间 http://some-namespace
,entry
不是 select 的正确名称;您必须包括名称空间。 GetElementsByTagName
有一个 overload with two arguments,其中第二个是命名空间。
你这里有几个问题:
您使用的是旧的 XmlDocument
API,它对命名空间的处理有些不便。具体来说:
XmlNode.GetElementsByTagName(string)
是 命名空间未知的 。它匹配 "raw" 限定元素名称,可能包括前缀。
这个方法,微软写在documentation
Note
It is recommended that you use the XmlNode.SelectNodes
or XmlNode.SelectSingleNode
method instead of the GetElementsByTagName
method.
XmlNode.SelectSingleNode(string)
,相反,是命名空间感知的,而select只是空命名空间中的元素。
来自docs:
If the XPath expression does not include a prefix, it is assumed that the namespace URI is the empty namespace. If your XML includes a default namespace, you must still use the XmlNamespaceManager
and add a prefix and namespace URI to it; otherwise, you will not get a selected node.
这两种方法之间的这种不一致解释了为什么您的代码部分有效,因为您的 XML 文档中的所有元素都属于 http://purl.org/atom/ns#
命名空间。
如果缩进 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")
的调用也失败了。
因此下面的代码将工作并正确select您的条目名称:
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);
}
示例 fiddle #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);
}
示例 fiddle #2 here.
我从服务收到以下字符串列表
<?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>
我试图通过内部文本获取 name 的值,但无法这样做:
即
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;
}
相反,我得到的是 object is null 异常。
"ExceptionMessage": "Object reference not set to an instance of an object.",
感谢任何指点。
给定的样本无效XML:
- 它没有文档元素
- 它没有 XML 声明
- 它包含未闭合的打开元素
<author>
由于这些原因中的任何一个,我不希望它被解析。
然而,NullReferenceException 没有正确传达失败的原因,因此这里可能还有其他原因。使用您的调试器确定哪一行抛出此异常。
假设您遗漏了一些 XML 而它实际上是有效的,这也可能是由于未指定您打算 select 的元素的名称空间造成的。如果文档具有目标命名空间 http://some-namespace
,entry
不是 select 的正确名称;您必须包括名称空间。 GetElementsByTagName
有一个 overload with two arguments,其中第二个是命名空间。
你这里有几个问题:
您使用的是旧的
XmlDocument
API,它对命名空间的处理有些不便。具体来说:XmlNode.GetElementsByTagName(string)
是 命名空间未知的 。它匹配 "raw" 限定元素名称,可能包括前缀。这个方法,微软写在documentation
Note
It is recommended that you use the
XmlNode.SelectNodes
orXmlNode.SelectSingleNode
method instead of theGetElementsByTagName
method.XmlNode.SelectSingleNode(string)
,相反,是命名空间感知的,而select只是空命名空间中的元素。来自docs:
If the XPath expression does not include a prefix, it is assumed that the namespace URI is the empty namespace. If your XML includes a default namespace, you must still use the
XmlNamespaceManager
and add a prefix and namespace URI to it; otherwise, you will not get a selected node.
这两种方法之间的这种不一致解释了为什么您的代码部分有效,因为您的 XML 文档中的所有元素都属于
http://purl.org/atom/ns#
命名空间。如果缩进 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")
的调用也失败了。
因此下面的代码将工作并正确select您的条目名称:
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);
}
示例 fiddle #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);
}
示例 fiddle #2 here.