为什么XmlReader跳过元素? [英] Why is the XmlReader skipping elements?
问题描述
请注意,此问题特定于 XmlReader
,而不是使用 XDocument
还是 XmlReader
.
Please note this question is specific to XmlReader
and not whether to use XDocument
or XmlReader
.
我有一个 XML 片段:
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>";
}
我还有一个扩展方法,例如:
I also have an extension method as:
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
元素:
I then try to get the two book
elements by doing:
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);
}
但是,我只得到第一个元素,调试显示,只要得到第一个元素,读者就会跳到第二个 book
元素的 title
.
However I only get the first element, debugging shows that as soon as I get the first element the reader jumps to the title
of the second book
element.
The solution is inspired from HERE
非常感谢您的帮助.
推荐答案
问题是,如果没有中间的空格,则对 XNode.ReadFrom()
的调用将使XML阅读器定位就在下一个元素.然后, while
条件会立即使用此元素,然后我们才能对其进行检查.解决方法是不要在此之后立即调用 XmlReader.Read()
,而是继续检查节点(因为读取已隐式完成):
The problem is that, if there is no intervening whitespace, the call to XNode.ReadFrom()
will leave the XML reader positioned right at the next element. The while
condition then immediately consumes this element before we can check it. The fix is to not call XmlReader.Read()
immediately afterwards, but to continue checking for nodes (as the read has been done implicitly):
while (reader.Read()) {
while (reader.NodeType == XmlNodeType.Element
&& reader.Name.Equals(elementName, StringComparison.InvariantCulture)) {
yield return XNode.ReadFrom(reader) as XElement;
}
}
(如果不清楚,则循环中的 if
已更改为 while
.)
(In case it's not clear, the if
in the loop has been changed to a while
.)
这篇关于为什么XmlReader跳过元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!