2008-09-25 12 views
98

Bei der XML-Generierung aus XmlDocument in .NET wird ein leeres xmlns-Attribut angezeigt, wenn zum ersten Mal ein Element ohne einen zugeordneten Namespace eingefügt wird; Wie kann dies verhindert werden?Wie verhindert man leere Xmlns-Attribute in der Ausgabe von .NET XmlDocument?

Beispiel:

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

Ausgang:

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

Wunsch Ausgang:

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

Gibt es eine Lösung für den XmlDocument Code, nicht etwas, das tritt nach Konvertieren des Dokuments in eine Zeichenfolge mit OuterXml?

Mein Argument dafür ist zu sehen, ob ich die Standard-XML eines bestimmten Protokolls mit XmlDocument-generierten XML übereinstimmen kann. Das leere xmlns Attribut Mai nicht brechen oder einen Parser zu verwechseln, aber es ist auch nicht in irgendeiner Verwendung, die ich dieses Protokoll gesehen habe.

Antwort

95

Dank Jeremy Lew Antwort und eine bisschen herumspielen, habe ich herausgefunden, wie leer xmlns Attribute entfernen: im Namespace Root-Knoten übergeben, wenn alle untergeordneten Knoten zu schaffen Sie wollen nicht auf einen Präfix haben. Wenn Sie einen Namespace ohne Präfix im Stammverzeichnis verwenden, bedeutet dies, dass Sie denselben Namespace für untergeordnete Elemente verwenden müssen, damit sie und keine Präfixe haben.

Fest Code:

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); 

Vielen Dank allen für alle Ihre Antworten, die mich in die richtige Richtung geführt!

+1

Genau. Wenn Sie das Element in den Namespace "whatever: name-space-1.0" einfügen, bedeutet dies, dass das leere Attribut xmlns (das es in keinen Namespace stellt) nicht hinzugefügt wird, wenn es serialisiert wird. Wenn Sie eine Aktualisierung benötigen, wie Namespaces funktionieren, werfen Sie einen Blick auf http://www.jclark.com/xml/xmlns.htm – JeniT

+1

Achtung: Elemente brauchen dies (oder das vielleicht bessere 'doc.DocumentElement.NamespaceURI') aber don Wenn Sie keinen Namespace für 'CreateAttribute()' angeben, erhalten Sie 'xmlns: psomething', auch wenn es sich um dieselbe URL handelt. –

9

Wenn das <loner> Element in Ihrem XML-Beispiel nicht die xmlns Standardnamespace-Deklaration auf sie hat, dann wäre es eher im whatever:name-space-1.0 Namespace als in keinem Namensraum zu sein. Wenn das, was Sie wollen, müssen Sie das Element in diesem Namensraum erstellen:

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

Wenn Sie das <loner> wollen Element in keinem Namensraum zu sein, dann ist die XML, die produziert worden ist genau das, was Sie brauchen, und Sie shouldn Machen Sie sich keine Sorgen um das Attribut xmlns, das automatisch für Sie hinzugefügt wurde.

+2

Das Problem liegt bei nicht-konforme XML-Parser (in der Regel von Microsoft), die nicht mit xmnls = "" zurechtkommen). –

+2

/. namens. Sie wollen ihren zufälligen MS-Bashing-Kommentar zurück. – Will

+0

@W. Craig Trader - kann nicht sagen, dass ich das als ein Problem angetroffen habe. Beispiel? – Kev

7

Da sich root in einem Namespace ohne Präfix befindet, muss jedes Kind des root, das nicht namespaced sein möchte, wie Ihr Beispiel ausgegeben werden. Die Lösung wäre das Wurzelelement Präfix wie folgt:

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

Code:

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); 
+0

Danke, aber das Hinzufügen des Namespace zum eigentlichen Root würde mein XML in Bezug auf das bestimmte Protokoll, mit dem ich arbeite, unterbrechen. –

+0

Ah! Ich realisierte mehr, was Sie sagten, und berücksichtigte es, als ich meine eigene Antwort schrieb. Danke Jeremy –

0

Wenn möglich, erstellen Sie eine Serialisierung Klasse dann tun:

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

Es ist sicherer, und Sie kann die Namespaces mit Attributen steuern, wenn Sie wirklich mehr Kontrolle benötigen.

0

Ich habe das Problem mit dem Factory-Muster gelöst. Ich habe eine Factory für XElement-Objekte erstellt. Als Parameter für die Instanziierung der Factory habe ich ein XNamespace-Objekt angegeben. Jedes Mal, wenn ein XElement von der Factory erstellt wird, wird der Namespace automatisch hinzugefügt. Hier ist der Code der Fabrik:

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); 
    } 
} 
+0

Das OP fragte nach 'XmlDocument', nicht nach' XDocument'. –

64

Dies ist eine Variante von JeniT Antwort (Danke sehr, sehr viel btw!)

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

Diese entfällt die Notwendigkeit, den Namensraum überall zu kopieren oder zu wiederholen.

+3

Beste Antwort nach mir. Wir müssen nicht wissen, was der Standard-Namespace für Dokumente ist (nützlich, wenn wir keine xml-Datei von Grund auf neu erstellen, z. B. in Szenarien zum Lesen und Ändern). – MuiBienCarlota

-1

Ja, Sie können die XMLNS aus dem XmlElement verhindern. Erste Erstellen Zeit es kommt: wie die

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

Ändern Sie den Code: Und XML-Namespace wie diese

C# -Code passieren:

XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1"); 
bookElement.SetAttribute("lat", "30.53597"); 
bookElement.SetAttribute("lon", "97.753324");