2012-08-27 84 views
0

我需要一個XML文件並從輸入文件的數千個重複節點中創建多個輸出xml文件。源文件 「AnimalBatch.xml」 看起來是這樣的:我需要將大型XML文件拆分爲多個輸出xml,使用XmlTextReader

<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Animal id="1001">
<Quantity>One</Quantity>
<Adjective>Red</Adjective>
<Name>Rooster</Name>
</Animal>
<Animal id="1002">
<Quantity>Two</Quantity>
<Adjective>Stubborn</Adjective>
<Name>Donkeys</Name>
</Animal>
<Animal id="1003">
<Quantity>Three</Quantity>
<Color>Blind</Color>
<Name>Mice</Name>
</Animal>
</Animals>

但在實際上,有在它沒有CR/LF字符。文本的實際流是這樣的:

<?xml version="1.0" encoding="utf-8" ?><Animals><Animal id="1001"><Quantity>One</Quantity><Adjective>Red</Adjective><Name>Rooster</Name></Animal><Animal id="1002"><Quantity>Two</Quantity><Adjective>Stubborn</Adjective><Name>Donkeys</Name></Animal><Animal id="1003"><Quantity>Three</Quantity><Color>Blind</Color><Name>Mice</Name></Animal></Animals>

程序需要拆分的重複「動物」,併產生3個文件名爲:Animal_1001.xml,Animal_1002.xml和Animal_1003.xml

我對此有一個使用XmlDocument的問題,該問題已經得到解答。
參見:[拆分XML文件轉換成使用XmlDocument的多個XML] [1]

這個問題是鄰接如何使用的XmlReader抓取元件和創建從他們的XmlDocument元素。


Animal_1001.xml:
<?xml version="1.0" encoding="utf-8"?>
<Animal>
<Quantity>One</Quantity>
<Adjective>Red</Adjective>
<Name>Rooster</Name>
</Animal>


Animal_1002.xml
<?xml version="1.0" encoding="utf-8"?>
<Animal>
<Quantity>Two</Quantity>
<Adjective>Stubborn</Adjective>
<Name>Donkeys</Name>
</Animal>


Animal_1003。XML>
<?xml version="1.0" encoding="utf-8"?>
<Animal>
<Quantity>Three</Quantity>
<Adjective>Blind</Adjective>
<Name>Mice</Name>
</Animal>

這裏是工作的代碼 - 但只有當有輸入文件換行符:

static void SplitXMLReader() 
    { 
     string strFileName; 
     string strSeq; 

     XmlReader doc = XmlReader.Create("C:\\AnimalBatch.xml"); 

     while (doc.Read()) 
     { 
      if (doc.Name=="Animal") 
      { 
       strSeq = doc.GetAttribute("id"); 

       XmlDocument outdoc = new XmlDocument(); 
       XmlDeclaration xmlDeclaration = outdoc.CreateXmlDeclaration("1.0", "utf-8", null); 
       XmlElement rootNode = outdoc.CreateElement(doc.Name); 

       rootNode.InnerXml = doc.ReadInnerXml(); 
       outdoc.InsertBefore(xmlDeclaration, outdoc.DocumentElement); 
       outdoc.AppendChild(rootNode); 

       strFileName = "Animal_" + strSeq + ".xml"; 
       outdoc.Save("C:\\" + strFileName); 
      } 
     } 
    } 

當這個程序運行在「AnimalBatch.xml」的副本上時,回車後每個元素返回 - 它的工作原理,並根據需要創建Animal_xxxx.xml文件。當AnimalBatch.xml看起來像未格式化文本的流 - 它得到第一個動物 - 並可以得到它的ID爲1001,並輸出文件確定。它能夠讀取隨後的動物元素,但不能獲得「id」屬性 - 最終編寫名爲「Animal_.xml」的輸出文件 - 顯然它試圖從屬性讀取的strSeq變量爲空或空白。截至去年底,第二個文件只包含此:

<?xml version="1.0" encoding="utf-8"?>
<Animal />

這使我相信,XmlReader中,至少到doc.Read()方法,(DOC的程度。 Name ==「Animal」)聲明或更高版本的「strSeq = doc.GetAttribute(」id「); 」 - 如果在<Animal id="1002">標記之後存在CR/LF,則工作方式不同。

我想我真正的問題是 - 當它確實doc.GetAttribute(「id」);文檔中的光標在哪裏?爲什麼它不能在「1001」之後得到那些 - 這是行得通的?

John說XML不關心格式化 - 而且我一直都這麼認爲 - 但這一點令人困惑。另外 - 對於我的應用程序,我可以得到XML的唯一方法是無格式的,因爲我通過SSIS從SQL中取出,它是一個文本流,而不是XML對象。

+0

僅供參考,不使用'新XmlTextReader'。改爲使用'XmlReader.Create'。 –

+0

約翰 - 我將不得不給你一個站立的起立鼓掌。您的觀察使用XmlReader而不是XmlTextReader是解決方案。文本閱讀器的問題顯然與它不認識隨後的「動物」元素有關(它會得到第一個 - 但是當我嘗試獲得屬性「ID」時 - 它只發現第一個 - 我發現現在可以運行的代碼 –

+0

John - 我發現我的輸入文件沒有如我的示例中所示的CR/LF的「格式化」,是否這樣?意思是我必須使用xmlTextReader?我已經使用它獲得了一定程度的成功(即,我可以獲得外部xml - 只是無法提取ID屬性)也許我需要在一個單獨的問題中指定此內容 –

回答

0

首先,我看不到你在任何地方給outdoc分配任何東西......我想你想用當前節點數據填充它,然後保存它?另外,我會創建一個XmlDocument對象,然後在循環中清除/填充它,在循環中創建新對象幾千次並不是那麼好的想法...

另請注意,XmlReader正在移動一個元素一次。所以,你的代碼會自動取款機:

  1. 呼叫XmlRead()並沒有陷入任何情況下(它會讀取第一?xml聲明)
  2. 呼叫XmlRead()一次,陷入的情況下,移動到id屬性和寫入空文件。
  3. 致電XmlRead()10次 \,跳過一切,直到下一個Animal元素。

<Animal>標籤內部獲取數據的一種解決方案類似於This example on msdn

二是想到更方便的方法,例如ReadInnerXml方法與ReadToFollowing。 另外,請看GetAttribute method

我的做法是:

  1. string toFile = "";
  2. 讀文件,直到<Animal>標籤。
  3. GetAttribute("id");
  4. toFile = ReadInnerXml();
  5. toFile到文件;)
  6. doc.ReadToFollowing("Animal");

有了可能一些小的調整,因爲我不檢查我寫的東西與編譯器...

0

您需要在outdoc上創建根節點。使用此代碼:

static void SplitXMLTextReader() 
    { 

     string strFileName; 
     string strSeq = "0"; 

     XmlTextReader doc = new XmlTextReader(("C:\\AnimalBatch.xml")); 
     doc.WhitespaceHandling = WhitespaceHandling.None; 

     while (doc.Read()) 
     { 
      switch (doc.Name) 
      { 
       case "Animal": 
        XmlDocument outdoc = new XmlDocument(); 
        XmlDeclaration xmlDeclaration = outdoc.CreateXmlDeclaration("1.0", "utf-8", null); 
         XmlElement rootNode = outdoc.CreateElement(doc.Name); 
        rootNode.InnerXml = doc.ReadInnerXml(); 
        outdoc.InsertBefore(xmlDeclaration, outdoc.DocumentElement); 
        outdoc.AppendChild(rootNode); 


        doc.MoveToFirstAttribute(); 
        if (string.Compare(doc.Name, "id", true) == 0) 
        { 
         strSeq = doc.Value; 
        } 
        strFileName = "Animal_" + strSeq + ".xml"; 
        outdoc.Save("C:\\" + strFileName); 
        break; 
      } 
     } 

    } 
+0

該解決方案非常接近,但存在一個錯誤:我得到兩個輸出xml文件,名爲Animal_0002.xml和Animal_003.xml。Animal_0002.xml具有完整的輸出文件,但具有第一個動物的內容(一隻紅公雞),而Animal_0002.xml就是這樣一個空標籤,但不是有效載荷。我認爲抓取id的程序部分(開始「doc.MoveToFirstAttribute()」的部分)可能需要從outdoc獲取它的信息 - 在它被附加到outdoc之後。但是 - 你的代碼非常接近。如何在doc.Read()循環中創建outdoc XmlDocuments –

0
static void SplitXMLReader() 
{ 
    string strFileName; 
    string strSeq; 

    XmlReader doc = XmlReader.Create("C:\\AnimalBatch.xml"); 

    while (doc.Read()) 
    { 
     if (doc.Name=="Animal") 
     { 
      strSeq = doc.GetAttribute("id"); 

      XmlDocument outdoc = new XmlDocument(); 
      XmlDeclaration xmlDeclaration = outdoc.CreateXmlDeclaration("1.0", "utf-8", null); 
      XmlElement rootNode = outdoc.CreateElement(doc.Name); 

      rootNode.InnerXml = doc.ReadInnerXml(); 
      outdoc.InsertBefore(xmlDeclaration, outdoc.DocumentElement); 
      outdoc.AppendChild(rootNode); 

      strFileName = "Animal_" + strSeq + ".xml"; 
      outdoc.Save("C:\\" + strFileName); 
     } 
    } 
} 
+0

OMG - 我發現我的「Batch」xml文件是一個文本流 - 並沒有在我的「AnimalBatch.xml中指定的CRLF 「示例文件上面的'解決方案'在節點之後存在CRLF時起作用 - 但是如果沒有,則不能使用XmlReader,我又回到了使用XmlTextReader的工作。Pooh。 –

+0

在XML輸入文件中沒有換行符時在另一個問題下執行此操作:http://stackoverflow.com/questions/12188383/parsing-a-large-xml-file-to-multiple-output-xmls-using- XMLReader的-得到前所未有/ 12189807#12189807 –

相關問題