请注意,此问题仅针对XmlReader
,而不是{@ 1}}或XDocument
。
我有一个 XML 片段:
XmlReader
我还有一个扩展方法:
private string GetXmlFragment()
{
return @"<bookstore>
<book genre='novel' ISBN='10-861003-324'>
<title>The Handmaid's Tale</title>
<price>19.95</price>
</book>
<book genre='novel' ISBN='1-861001-57-5'>
<title>Pride And Prejudice</title>
<price>24.95</price>
</book>
</bookstore>";
}
然后我尝试通过执行以下操作来获取两个public static IEnumerable<XElement> GetElement(this XmlReader reader, string elementName)
{
reader.MoveToElement();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element
&& reader.Name.Equals(elementName, StringComparison.InvariantCulture))
{
yield return XNode.ReadFrom(reader) as XElement;
}
}
}
元素:
book
但是我只得到第一个元素,调试显示,只要我得到第一个元素,读者就会跳转到第二个var xmlReaderSettings = new XmlReaderSettings
{
CheckCharacters = false,
ConformanceLevel = ConformanceLevel.Fragment,
IgnoreComments = true,
IgnoreWhitespace = true,
IgnoreProcessingInstructions = true
};
using (var stringReader = new StringReader(this.GetXmlFragment()))
using (var xmlReader = XmlReader.Create(stringReader, xmlReaderSettings))
{
xmlReader.GetElement("book").Count().ShouldBe(2);
}
元素的title
。
该解决方案的灵感来自HERE
非常感谢任何帮助。
答案 0 :(得分:3)
问题在于,如果没有插入的空格,对XNode.ReadFrom()
的调用将使XML阅读器位于下一个元素的正确位置。 while
条件然后立即消耗此元素,然后才能检查它。修复之后不要立即调用XmlReader.Read()
,而是继续检查节点(因为读取已经隐式完成):
while (reader.Read()) {
while (reader.NodeType == XmlNodeType.Element
&& reader.Name.Equals(elementName, StringComparison.InvariantCulture)) {
yield return XNode.ReadFrom(reader) as XElement;
}
}
(如果不清楚,循环中的if
已更改为while
。)
答案 1 :(得分:1)
public static IEnumerable<XElement> GetElement(this XmlReader reader, string elementName)
{
while (!reader.EOF)
if (reader.NodeType == XmlNodeType.Element && reader.Name == "book")
yield return XNode.ReadFrom(reader) as XElement;
else
reader.Read();
}
答案 2 :(得分:0)
代码正在跳过所有其他书签,因为书签会立即相互跟随。 read方法将读取器留在下一个book标签上,然后read方法在读取跳过元素的第二个book标签之前移动。试试我开发的以下代码,并始终有效。
public static IEnumerable<XElement> GetElement(XmlReader reader, string elementName)
{
List<XElement> books = new List<XElement>();
while (!reader.EOF)
{
if(reader.Name != "book")
{
reader.ReadToFollowing("book");
}
if(!reader.EOF)
{
books.Add((XElement)XElement.ReadFrom(reader));
}
}
return books;
}
答案 3 :(得分:0)
正如其他人所说,XNode.ReadFrom正在推动读者进入下一本书的开放标签(如果它们之间没有空格)那么reader.Read会前进到该标签的内部文本。
有关详细信息,请参阅此处:
https://stackoverflow.com/a/26788230/3850405
修复扩展方法:
public static IEnumerable<XElement> GetElement(this XmlReader reader, string elementName)
{
reader.MoveToElement();
reader.Read();
while (!reader.EOF)
{
if (reader.NodeType == XmlNodeType.Element
&& reader.Name.Equals(elementName, StringComparison.InvariantCulture))
{
yield return XNode.ReadFrom(reader) as XElement;
}
else
{
reader.Read();
}
}
}