.NETのXmlDocumentからの出力で空白のxmlns属性を防ぐ方法は?


118

.NETでXmlDocumentからXMLを生成する場合、関連付けられた名前空間のないxmlns要素が初めて挿入されると、空白の属性が表示されます。これをどのように防ぐことができますか?

例:

XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root",
    "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner"));
Console.WriteLine(xml.OuterXml);

出力:

<root xmlns="whatever:name-space-1.0"><loner xmlns="" /></root>

望ましい出力:

<root xmlns="whatever:name-space-1.0"><loner /></root>

ドキュメントを文字列に変換した後にXmlDocument発生するものではなく、コードに適用可能な解決策はありますか?OuterXml

これを行う理由は、XmlDocumentで生成されたXMLを使用して、特定のプロトコルの標準XMLと一致できるかどうかを確認することです。空のxmlns属性パーサーを壊したり混乱させたりすることはないかもしれませんが、このプロトコルについて私が見たどのような使用法にも存在しません。

回答:


111

Jeremy Lewの回答ともう少し遊んでみて、空白のxmlns属性を削除する方法を見つけました。プレフィックスを付けたくない子ノードを作成するときにルートノードの名前空間を渡します。ルートで接頭辞なしの名前空間を使用すると、子要素に同じ名前空間を使用して、子要素に接頭辞を付けないようにする必要があります。

修正済みコード:

XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root", "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner", "whatever:name-space-1.0")); 
Console.WriteLine(xml.OuterXml);

私を正しい方向に導いたすべての答えにみんなに感謝します!


1
正確に。「whatever:name-space-1.0」名前空間に<loner>要素を配置すると、シリアル化されたときに空のxmlns属性(名前空間に配置されない)が追加されません。名前空間の動作を
更新

2
要注意:要素はこれを必要とする(またはおそらくそれよりも良いdoc.DocumentElement.NamespaceURI)が、同じURIであっても名前空間を指定しないCreateAttribute()でくださいxmlns:psomething
Jason Kleban 2015

87

これはJeniTの回答の変形です(ありがとうございました!)

XmlElement new_element = doc.CreateElement("Foo", doc.DocumentElement.NamespaceURI);

これにより、名前空間をどこにでもコピーまたは繰り返す必要がなくなります。


3
私によると最高の反応。ドキュメントのデフォルト名前空間が何であるかを知る必要はありません(XMLファイルを最初から作成しない場合、つまり読み取りと変更のシナリオで有用です)。
MuiBienCarlota 2012年

11

<loner>サンプルXMLの要素にxmlnsデフォルトのネームスペース宣言がない場合、そのエレメントはwhatever:name-space-1.0ネームスペースではなくネームスペースにあります。それが必要な場合は、その名前空間に要素を作成する必要があります。

xml.CreateElement("loner", "whatever:name-space-1.0")

あなたがしたい場合は<loner>要素がありません名前空間にあるように、その後、生産されていますXMLは、何が必要正確に、そして、あなたは心配してはいけませんxmlns、あなたのために自動的に追加されています属性。


3
問題は、xmnls = ""に対応できない非準拠のXMLパーサー(通常はMicrosoft製)にあります。
Craig Trader

2
/。呼ばれた。彼らは自分のランダムなMSバッシングコメントを返して欲しい。

@W。Craig Trader-問題として発生したとは言えません。例?
ケフ

1
正解です。<loner />ノードに名前空間を持たせたくありませんが、名前空間属性(xmlns)を空白にしたくありません。私の推論は、このように設定された特定のプロトコルのXML出力と一致できるかどうかを確認することです。
Neil C. Obremski、2008

5
それはランダムバッシングではありませんでした。Microsoft Updater Application BlockはXMLマニフェストを使用して、クライアントに何を配信するかを決定します。残念ながら、マニフェストパーサーはxmlns = ""に対応できません。空のxmlns属性を取り除くポストプロセッサーを作成する必要がありました。
クレイグトレーダー

7

ルートは接頭辞のない名前空間にあるため、名前空間を解除したいルートの子は、例のように出力する必要があります。解決策は、ルート要素に次のようにプレフィックスを付けることです。

<w:root xmlns:w="whatever:name-space-1.0">
   <loner/>
</w:root>

コード:

XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement( "w", "root", "whatever:name-space-1.0" );
doc.AppendChild( root );
root.AppendChild( doc.CreateElement( "loner" ) );
Console.WriteLine(doc.OuterXml);

おかげで、実際のルートに名前空間を追加すると、使用している特定のプロトコルに関連して私のXMLが壊れてしまいます。
Neil C. Obremski、2008

ああ!私はあなたが言っていることをもっと理解し、自分の答えを書くときにそれを考慮しました。ジェレミーに感謝
ニール・C・オブレムスキー

0

可能であれば、シリアライゼーションクラスを作成してから、次の操作を行います。

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serializer = new XmlSerializer(yourType);
serializer.Serialize(xmlTextWriter, someObject, ns);

それはより安全であり、本当により多くの制御が必要な場合は、属性で名前空間を制御できます。


0

Factoryパターンを使用して問題を解決しました。XElementオブジェクトのファクトリーを作成しました。ファクトリーのインスタンス化のパラメーターとして、XNamespaceオブジェクトを指定しました。したがって、ファクトリによってXElementが作成されるたびに、名前空間が自動的に追加されます。これがファクトリーのコードです:

internal class XElementFactory
{
    private readonly XNamespace currentNs;

    public XElementFactory(XNamespace ns)
    {
        this.currentNs = ns;
    }

    internal XElement CreateXElement(String name, params object[] content)
    {
        return new XElement(currentNs + name, content);
    }
}

1
OPはXmlDocument、ではなく、について尋ねていましたXDocument
John Saunders

0

はい、XmlElementからXMLNSを防ぐことができます。最初の作成時間が来ます:そのように

<trkpt lat="30.53597" lon="-97.753324" xmlns="">
    <ele>249.118774</ele>
    <time>2006-05-05T14:34:44Z</time>
</trkpt>

コードを変更します。次のようにxml名前空間を渡します

C#コード:

XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1");
bookElement.SetAttribute("lat", "30.53597");
bookElement.SetAttribute("lon", "97.753324");
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.