Domanda

Quando si genera XML da XmlDocument in .NET, un attributo xmlns vuoto appare la prima volta che viene inserito un elemento senza uno spazio dei nomi associato; come può essere prevenuto?

Esempio:

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

Output:

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

Risultato desiderato:

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

Esiste una soluzione applicabile al XmlDocument codice, non qualcosa che si verifica dopo la conversione del documento in una stringa con OuterXml?

Il mio ragionamento per fare questo è vedere se posso abbinare l'XML standard di un protocollo particolare usando l'XML generato da XmlDocument. L'attributo <=> attributo potrebbe non rompere o confondere un parser, ma non è presente in nessun utilizzo che ho visto di questo protocollo.

È stato utile?

Soluzione

Grazie alla risposta di Jeremy Lew e un po 'più di gioco, ho capito come rimuovere gli attributi xmlns vuoti: passare nello spazio dei nomi del nodo radice quando si crea un nodo figlio che si desidera non avere un prefisso attivo. L'uso di uno spazio dei nomi senza un prefisso nella radice significa che è necessario utilizzare lo stesso spazio dei nomi sugli elementi figlio affinché anche non abbia prefissi.

Codice fisso:

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

Grazie a tutti per tutte le vostre risposte che mi hanno portato nella giusta direzione!

Altri suggerimenti

Questa è una variante della risposta di JeniT (Grazie mille a proposito!)

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

Questo elimina la necessità di copiare o ripetere lo spazio dei nomi ovunque.

Se l'elemento <loner> nel tuo XML di esempio non conteneva la xmlns dichiarazione dello spazio dei nomi predefinita, sarebbe nello spazio dei nomi whatever:name-space-1.0 anziché in nessuno spazio dei nomi. Se è quello che vuoi, devi creare l'elemento in quello spazio dei nomi:

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

Se vuoi che l'elemento <=> non sia nello spazio dei nomi, allora l'XML che è stato prodotto è esattamente quello che ti serve, e non dovresti preoccuparti dell'attributo <=> che è stato aggiunto automaticamente per te.

Poiché root si trova in uno spazio dei nomi non prefissato, qualsiasi figlio di root che vuole essere senza spazio dei nomi deve essere prodotto come il tuo esempio. La soluzione sarebbe quella di prefissare l'elemento root in questo modo:

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

codice:

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

Se possibile, creare una classe di serializzazione, quindi eseguire:

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

È più sicuro e puoi controllare gli spazi dei nomi con attributi se hai davvero bisogno di un maggiore controllo.

Ho risolto il problema utilizzando il modello di fabbrica. Ho creato una fabbrica per oggetti XElement. Come parametro per l'istanza della factory ho specificato un oggetto XNamespace. Quindi, ogni volta che un XElement viene creato dalla fabbrica, lo spazio dei nomi verrà aggiunto automaticamente. Ecco il codice della fabbrica:

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

Sì, puoi impedire XMLNS da XmlElement. Prima Creare l'ora che sta arrivando: così

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

Cambia il codice: e passa lo spazio dei nomi xml come questo

Codice C #:

XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1");
bookElement.SetAttribute("lat", "30.53597");
bookElement.SetAttribute("lon", "97.753324");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top