2016-04-28 54 views
2

请注意这个问题是专用于XmlReader而不是是否使用XDocumentXmlReader为什么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>"; 
} 

我也有一个扩展的方法:

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); 
} 

但是我只获得第一个元素,调试ging表明,只要我得到第一个元素,阅读器跳到第二个book元素的title

溶液从HERE

任何帮助的启发是非常赞赏。

+0

无法重现。你的方法在我的机器上产生一个包含两个元素的序列。你确定'this.GetXmlFragment()'生成你提供的XML吗? –

+0

奇怪的是,我已经更新了问题以包含方法 – babayi

+0

请参阅https://dotnetfiddle.net/ssrAG1。不知怎的,你的调试干扰了吗? –

回答

2

问题是,如果没有中间空格,对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
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(); 
} 
0

该代码正在跳过所有其他书标记,因为书标记紧跟着彼此。读取方法将读者留在下一个书签处,然后读取方法在读取第二个书签标签跳过元素之前移动。尝试下面我开发的代码,并始终工作。

 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; 
     } 
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(); 
     } 
    } 
} 
相关问题