2010-02-19 17 views
8

Ich habe eine Funktion, die XML für eine Liste Objekt erzeugt:XElement Funktion hinzufügen fügt xmlns = "" an die XElement

public XDocument ToXML() 
{ 
    foreach (var row in this) 
    { 
     var xml = row.ToXml(); 
     template.Root.Add(xml); 
    } 
    return template; 
} 

Die template.ToString() lautet: <RootElement xmlns="urn:testTools">

Die xml lautet: <Example><SubElement>testData</SubElement></Example>

Nachdem die Add-Funktion die template.ToString ausgeführt hat() lautet: <RootElement xmlns="urn:testTools"><Example xmlns=""><SubElement>testData</SubElement></Example>

Aus irgendeinem Grund wurde ein leerer Namespace hinzugefügt, wie kann ich das verhindern?

Antwort

7

Setzen Sie den Namespace für die Example- und SubElement-Elemente auf denselben Wert wie für das RootElement. Es fügt das xmlns = "" hinzu, um den Namespace für diese Elemente zu löschen.

+0

Ok ich verstehe jetzt, warum es das tut, danke! Aber es ist nur nützlich, wenn Sie verschiedene XML-Dateien mit unterschiedlichen Namespaces zusammenführen, nicht beim Erstellen eines einzelnen XML-Dokuments. Außerdem ist ein leerer Namespace-Tag nicht gültig. – JJoos

+1

@JJoos: ein leerer Namespace ist sicherlich XML gültig. Was lässt dich denken, dass es nicht ist? Beachten Sie auch, dass ein einzelnes XML-Dokument Elemente und Attribute aus vielen Namespaces enthalten kann. –

+0

@John Saunders Sie haben Recht, dachte, es war illegal wegen: http://www.w3.org/TR/REC-xml-names/ Abschnitt 2.2 erste Zeile. Art von verwirrend. Vielen Dank. – JJoos

0

Es könnte sein, dass Ihre Wurzel richtig geschlossen werden muss:

<RootElement xmlns="urn:testTools"> to <RootElement xmlns="urn:testTools"/> 
0

ich es gelöst, indem die Elemente mit einem regulären Ausdruck zu ersetzen. Fooles Lösung hat nicht funktioniert, weil ich nicht immer den genauen Namespace zu diesem Zeitpunkt im Code hatte.

Also hier ist mein schmutziger Hack, das funktioniert:

template = XDocument.Parse(new Regex("<ElementName.*>") 
    .Replace(template.ToString(SaveOptions.DisableFormatting), "<ElementName>")); 
+4

Seien Sie vorsichtig mit Ihren regulären Ausdrücken. XML ist keine reguläre Sprache, daher sollten reguläre Ausdrücke im Allgemeinen nicht für XML verwendet werden. –

9

Hier ist ein Beispiel, das XML ausgibt, ohne leere Namespaces. Beachten Sie die bizarre Linq-zentrische Syntax rootNamespace + "MyElementName", was das Geheimnis ist. Dies ist der gleiche Namespace wie das gesamte Dokument, daher ist kein xmlns-Zusatz notwendig. Dies verkettet einen XNamespace + eine Zeichenkette, was eine "+" - Überladung ist, die für Linq funktioniert und mit der Linq umgehen kann. (Ohne Linq könnte es ein Kompilierfehler sein, einen String und einen Nicht-String-Typ zu verketten). Beachten Sie, dass dies für eine C# -Projektdatei ausgeführt wurde, bei der es sich um eine praktische Xml-Datei handelt. Gib es auf eine Konsole oder ein Richtextbox-Steuerelement aus. Dann nimm den "rootNamespace +" raus und merke den Unterschied.

 XDocument doc = null; 

     using (StreamReader streamReader = 
      new StreamReader(@"myXml.csproj")) 
     { 
      doc = XDocument.Load(streamReader, LoadOptions.None); 
     } 
     XNamespace rootNamespace = doc.Root.Name.NamespaceName; 

     // A search which finds the ItemGroup which has Reference 
     // elements and returns the ItemGroup XElement. 
     XElement element = doc.Descendants().Where(p => p.Name.LocalName == "ItemGroup" 
      && p.Descendants().First<XElement>().Name.LocalName == "Reference").First<XElement>(); 

     // Create a completly new element with sub elements. 
     XElement referenceElement = new XElement(rootNamespace + "Reference", 
      new XElement(rootNamespace + "SpecificVersion", bool.FalseString), 
      new XElement(rootNamespace + "HintPath", "THIS IS A HINT PATH")); 

     // Add the new element to the main doc, to the end of the Reference elements. 
     element.Add(referenceElement); 

     // Add an attribute after the fact for effect. 
     referenceElement.SetAttributeValue("Include", "THIS IS AN INCLUDE"); 

     rtb.Text = doc.ToString(SaveOptions.None); 
+0

Danke, das sieht nach einer wirklich guten Lösung aus! Ich werde es nächstes Mal versuchen, wenn ich auf dieses Problem zugreife. – JJoos

+1

Vielen Dank! Das war sehr hilfreich! –

+1

Danke. Das war großartig! +1 –