web-dev-qa-db-ja.com

C#でXMLファイルに要素を追加する

次のような形式のXMLファイルがあります。

<Snippets>
  <Snippet name="abc">
    <SnippetCode>
      testcode1
    </SnippetCode>
  </Snippet>

  <Snippet name="xyz">
    <SnippetCode>      
     testcode2
    </SnippetCode>
  </Snippet>

  ...

</Snippets>

XDocumentを使用して要素を正常に読み込むことはできますが、新しい要素を追加するのに問題があります(多くの関数があり、そのほとんどはうまくいきませんでした)。これはどのように行われますか?新しい要素には、スニペット名タグとスニペットコードタグが含まれます。私の以前のアプローチは、ファイルを開き、文字列を使用して要素を手動で作成することでしたが、これは機能しますが、非常に悪い考えです。

私が試したもの:

XDocument doc = XDocument.Load(spath);
XElement root = new XElement("Snippet");
root.Add(new XElement("name", "name goes here"));
root.Add(new XElement("SnippetCode", "SnippetCode"));
doc.Element("Snippets").Add(root);
doc.Save(spath);

結果は次のとおりです。

<Snippet>
    <name>name goes here</name>
    <SnippetCode>
    code goes here
    </SnippetCode>
</Snippet>

名前タグが正しく生成されないことを除いて、正常に機能します。そのはず

<Snippet name="abc"> 

しかし、適切に生成することはできません。

33
rayanisran

あなたは近いですが、名前をXAttributeではなくXElementにしたい:

 XDocument doc = XDocument.Load(spath); 
 XElement root = new XElement("Snippet"); 
 root.Add(new XAttribute("name", "name goes here")); 
 root.Add(new XElement("SnippetCode", "SnippetCode")); 
 doc.Element("Snippets").Add(root); 
 doc.Save(spath); 
59
Jim Wooley

XAttributeの代わりに新しいXElementを作成する必要があります。次のようなものを試してください:

public static void Test()
{
    var xdoc = XDocument.Parse(@"
        <Snippets>

          <Snippet name='abc'>
            <SnippetCode>
              testcode1
            </SnippetCode>
          </Snippet>

          <Snippet name='xyz'>
            <SnippetCode>      
             testcode2
            </SnippetCode>
          </Snippet>

        </Snippets>");

    xdoc.Root.Add(
        new XElement("Snippet",
            new XAttribute("name", "name goes here"),
            new XElement("SnippetCode", "SnippetCode"))
    );
    xdoc.Save(@"C:\TEMP\FOO.XML");
}

これにより出力が生成されます。

<?xml version="1.0" encoding="utf-8"?>
<Snippets>
  <Snippet name="abc">
    <SnippetCode>
      testcode1
    </SnippetCode>
  </Snippet>
  <Snippet name="xyz">
    <SnippetCode>      
     testcode2
    </SnippetCode>
  </Snippet>
  <Snippet name="name goes here">
    <SnippetCode>SnippetCode</SnippetCode>
  </Snippet>
</Snippets>
6
JohnD

要素ではなく属性を追加する場合は、次のように言う必要があります。

XElement root = new XElement("Snippet");
root.Add(new XAttribute("name", "name goes here"));
root.Add(new XElement("SnippetCode", "SnippetCode"));

上記のコードは、次のXML要素を生成します。

<Snippet name="name goes here">
  <SnippetCode>SnippetCode</SnippetCode>
</Snippet> 
5
svick

構造に一致するクラスを作成し、インスタンスをコレクションに追加してから、コレクションをシリアル化および非シリアル化して、ドキュメントをロードおよび保存します。

4
Kell

XDocument.Root . Add を使用して要素を追加しました。ルートは、 XElement を返します。これには、追加のXElementの追加機能があります

2
Rob Haupt

これは上記の回答の拡張です。xmlに名前空間が定義されている場合(xmlns)、子を追加すると厄介な副作用が発生します-_xmlns = ""_が新しい子要素に追加されます。

あなたがしたいことは(追加する要素が彼の親と同じ名前空間に属すると仮定して)、親要素parentElement.GetDefaultNamespace()から名前空間を取得することです。

_var child = new XElement(parentElement.GetDefaultNamespace()+"Snippet", new XAttribute("Attr1", "42"), new XAttribute("Attr2", "22"));
child.Add(new XAttribute("Attr3", "777"));
parentElement.Add(child);
_

複数の名前空間を持つ親要素の場合、parentElement.GetDefaultNamespace()+"Snippet"からparentElement.GetNamespaceOfPrefix("namespacePrefixThatGoesWithColon")+"Snippet"に変更することにより、使用する名前空間を選択できます。

_var child = new XElement(parentElement.GetNamespaceOfPrefix("namespacePrefixThatGoesWithColon")+"Snippet", new XAttribute("Attr1", "42"), new XAttribute("Attr2", "22"));
_
1
<Snippet name="abc"> 

nameは属性であり、要素ではありません。それが失敗する理由です。 <Snippet>要素でSetAttributeを使用して調べます。

root.SetAttribute("name", "name goes here");

あなたが持っているもので必要なコードです。

0
Yatrix