2016-04-28 80 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(); 
     } 
    } 
}