4

XMLファイルを取得し、入力ファイルの繰り返しノードから複数の出力xmlファイルを作成する必要があります。ソースファイル「AnimalBatch.xml」は次のようになります。

<?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>

プログラムは、繰り返される「動物」を分割し、Animal_1001.xml、Animal_1002.xml、およびAnimal_1003.xmlという名前の3つのファイルを生成する必要があります。

各出力ファイルには、それぞれの要素(ルートになります)のみが含まれている必要があります。AnimalsBatch.xmlのid属性は、Animal_xxxx.xmlファイル名のシーケンス番号を提供します。id属性は出力ファイルにある必要はありません。


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>

XmlDocumentは、.Net 2.0で実行できる必要があるため、これを実行したいと思います。

私のプログラムは次のようになります。

    static void Main(string[] args)
    {
        string strFileName;    
        string strSeq;                    

        XmlDocument doc = new XmlDocument(); 
        doc.Load("D:\\Rick\\Computer\\XML\\AnimalBatch.xml");

        XmlNodeList nl = doc.DocumentElement.SelectNodes("Animal");

        foreach (XmlNode n in nl)
        {
            strSeq = n.Attributes["id"].Value;

            XmlDocument outdoc = new XmlDocument();
            XmlNode rootnode = outdoc.CreateNode("element", "Animal", "");

            outdoc.AppendChild(rootnode); // Put the wrapper element into outdoc

            outdoc.ImportNode(n, true);   // place the node n into outdoc
            outdoc.AppendChild(n);        // This statement errors:
            // "The node to be inserted is from a different document context."

            strFileName = "Animal_" + strSeq + ".xml";

            outdoc.Save(Console.Out);
            Console.WriteLine();
        }
        Console.WriteLine("END OF PROGRAM:  Press <ENTER>");
        Console.ReadLine();
    }

私は2つの問題があると思います。

A)ノードnのImportNodeをoutdocに実行した後、outdoc.AppendChild(n)を呼び出します。これは、「挿入されるノードは別のドキュメントコンテキストからのものです」と文句を言います。これがForEachループ内のノードnを参照するスコープの問題なのか、それともImportNode()またはAppendChildを適切に使用していないのかはわかりません。ImportNode()の2番目の引数はtrueに設定されています。これは、Animalの子要素(Quantity、Adjective、およびNameという任意の名前の3つのフィールド)を宛先ファイルに配置するためです。

B)2番目の問題は、Animal要素をoutdocに入れることです。''を取得していますが、ノードnをその中に配置できるように''が必要です。私の問題は私がどのようにやっているかだと思います:outdoc.AppendChild(rootnode);

xmlを表示するために、私は次のことを行っています。outdoc.Save(Console.Out); 私は出力ファイルにsave()するコードを持っています-outdocを適切にアセンブルできる限り、これは機能します。

同様の質問があります: 複数のXMLファイルにXMLを分割しますが、ソリューションコードをまだ理解していません。私はこのアプローチにかなり近づいていると思います、そしてあなたが提供できるどんな助けにも感謝します。

大きな入力ファイルを処理できる必要があるため、XmlReaderを使用してこれと同じタスクを実行します。また、XmlDocumentがすべてを読み込み、メモリの問題を引き起こす可能性があることを理解しています。

4

2 に答える 2

3

それはあなたが探しているもののように見える簡単な方法です

public void test_xml_split()
{
    XmlDocument doc = new XmlDocument();
    doc.Load("C:\\animals.xml");
    XmlDocument newXmlDoc = null;

    foreach (XmlNode animalNode in doc.SelectNodes("//Animals/Animal"))
    {
        newXmlDoc = new XmlDocument();
        var targetNode = newXmlDoc.ImportNode(animalNode, true);
        newXmlDoc.AppendChild(targetNode);
        newXmlDoc.Save(Console.Out);
        Console.WriteLine();
    }
}
于 2012-08-11T07:08:14.847 に答える
1

このアプローチは、「var targetnode」ステートメントを使用しなくても機能するようです。ForEach ループ内の outdoc の "Animal" 要素から、targetNode という XmlNode オブジェクトを作成します。元のコードで問題だった主な点は次のとおりだと思います。 A) nodelist nl を間違って取得していました。そして B) ノード n を「インポート」できませんでした。これは、特に doc に関連付けられていたためだと思います。独自のノードとして作成する必要がありました。

以前に提案されたソリューションの問題は、「var」キーワードの使用でした。私のプログラムは 2.0 を想定する必要があり、それは v3.0 で導入されました。簡潔であるという点で、Rogers のソリューションが気に入っています。私にとっては、それぞれのことを個別のステートメントとして実行したかったのです。

    static void SplitXMLDocument() 
    {
        string strFileName;
        string strSeq;
        XmlDocument doc = new XmlDocument();             // The input file
        doc.Load("D:\\Rick\\Computer\\XML\\AnimalBatch.xml");
        XmlNodeList nl = doc.DocumentElement.SelectNodes("//Animals/Animal");

        foreach (XmlNode n in nl)
        {
            strSeq = n.Attributes["id"].Value;           // Animal nodes have an id attribute

            XmlDocument outdoc = new XmlDocument();      // Create the outdoc xml document
            XmlNode targetNode = outdoc.CreateElement("Animal"); // Create a separate node to hold the Animal element

            targetNode = outdoc.ImportNode(n, true);     // Bring over that Animal
            targetNode.Attributes.RemoveAll();           // Remove the id attribute in <Animal id="1001">

            outdoc.ImportNode(targetNode, true);         // place the node n into outdoc
            outdoc.AppendChild(targetNode);              // AppendChild to make it stick

            strFileName = "Animal_" + strSeq + ".xml";                
            outdoc.Save(Console.Out); Console.WriteLine();
            outdoc.Save("D:\\Rick\\Computer\\XML\\" + strFileName);
            Console.WriteLine();
        }
    }
于 2012-08-12T02:11:48.407 に答える