请注意,此问题特定于XmlReader而不是是否使用XDocument或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>";
}
Run Code Online (Sandbox Code Playgroud)
我还有一个扩展方法:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试通过执行以下操作来获取这两个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);
}
Run Code Online (Sandbox Code Playgroud)
然而,我只得到第一个元素,调试显示,一旦我得到第一个元素,读者就会跳转到title第二个book元素。
该解决方案的灵感来自于HERE
任何帮助深表感谢。
问题是,如果没有中间的空格,则调用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;
}
}
Run Code Online (Sandbox Code Playgroud)
(如果不清楚,if循环中的 已更改为while。)