簡體   English   中英

使用XmlReader獲取XML文檔的所有元素(流式傳輸)

[英]Using XmlReader to get all elements of a XML document (streaming)

我正在嘗試解析從流中讀取的xml文檔,查找元素並將其作為XElements返回。 我希望能成為一個更通用的閱讀器,該閱讀器將獲取文檔中的每個元素,以便可以在調用函數中使用linq查詢來過濾所需的內容。 因此,假設我想從以下xml中獲取“ header”,“ book”和“ bookdata”元素:

<parent>
  <header>
    <data>text</data>
  </header>
  <books>
    <book>
      <bookdata>
        <title>book 1 title</title>
        <author>author 1</author>
      </bookdata>
      <otherinfo>info1</otherinfo>
    </book>
    <book>
      <bookdata>
        <title>book 2 title</title>
        <author>author 2</author>
      </bookdata>
      <otherinfo>info2</otherinfo>
    </book>
  </books>
</parent>

我已經基於Leonard Lobel的代碼實現了以下內容

private static IEnumerable<XElement> GetElements(Stream data)
{
    using (XmlReader reader = CreateSecureXmlReader(data))
    {
        reader.MoveToContent();
        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element)
            {
                var e = XElement.ReadFrom(reader) as XElement;
                yield return e;
            }
        }
    }
}

它被稱為如下:

var elements = from el in GetElements(stream)
               where el.Name == "header" ||
               el.Name == "book" ||
               el.Name == "bookdata"
               select el;

foreach (var xElement in elements)
{
     Console.WriteLine(xElement.Name);
}

問題在於,一旦它讀取一個元素作為XElement,它將向前跳過並且無法在該元素內尋找匹配項。 即我得到的輸出:

header

因為讀取並返回了標頭,(出於某種原因跳過了父級)。 但是隨后它讀取“ books”,並以XElement的形式返回它,此時,我假設XmlReader接下來查看“ books”之后的內容,這只是一些結束元素和文檔的結尾。 沒有機會在內部查找“ book”和“ bookdata”。

在倫納德·洛貝爾(Leonard Lobel)的示例中,他傳入了要查找的元素名稱,但是即使我傳入了所需元素的名稱,我仍然遇到了問題,即“書”被消耗掉了,並且在里面看不到用於“ bookdata”。

如果有人知道我如何查看所有元素並將它們作為XElement返回,或者有更好的解決方案來查找和返回這兩個元素及其子元素,那么將不勝感激。

像這樣實現leonard lobels方法(注意參數):

    private static IEnumerable<XElement> StreamElements(string fileName, params string[] elementsName)         
    {
          using (var rdr = XmlReader.Create(fileName))
          {
              rdr.MoveToContent();
              while (rdr.Read())
              {
                  if ((rdr.NodeType == XmlNodeType.Element) && (elementsName.Contains(rdr.Name)))
                  {
                      var e = XElement.ReadFrom(rdr) as XElement;
                      yield return e;
                  }
              }
              rdr.Close();
          }
     }

在您的代碼中(這是一個示例,您可以按自己的方式實現):

List<XElement> myElements = new List<XElement>();
foreach (var item in StreamElements("YourXMLfile.xml", "book", "bookdata", "header"))
{
     myElements.Add(item);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM