web-dev-qa-db-fra.com

Comment empêcher les attributs xmlns vides dans la sortie du XmlDocument de .NET?

Lors de la génération XML à partir de XmlDocument dans .NET, un attribut xmlns vide apparaît la première fois qu'un élément sans un espace de noms associé est inséré; comment éviter cela?

Exemple:

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

Sortie:

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

Souhaité Sortie:

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

Existe-t-il une solution applicable au code XmlDocument, pas quelque chose qui se produit après conversion du document en une chaîne avec OuterXml?

Mon raisonnement pour cela est de voir si je peux faire correspondre le XML standard d'un protocole particulier en utilisant du XML généré par XmlDocument. L'attribut vide xmlnspeut ne casse ni ne confond un analyseur, mais il n'est également présent dans aucune utilisation que j'ai vue de ce protocole.

112
Neil C. Obremski

Grâce à la réponse de Jeremy Lew et à un peu plus de jeu, j'ai compris comment supprimer les attributs vierges xmlns: passer dans l'espace de noms du nœud racine lors de la création du nœud enfant que vous souhaitez pas avoir un préfixe sur. L'utilisation d'un espace de noms sans préfixe à la racine signifie que vous devez utiliser ce même espace de noms sur les éléments enfants pour qu'ils également ne disposent pas de préfixes.

Code fixe:

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

Merci à tous pour toutes vos réponses qui m'ont conduit dans la bonne direction!

103
Neil C. Obremski

Ceci est une variante de la réponse de JeniT (Merci beaucoup, merci!)

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

Cela évite d'avoir à copier ou répéter l'espace de noms partout.

82
C Johnson

Si la <loner> l'élément de votre exemple XML n'avait pas la déclaration d'espace de noms xmlns par défaut, il se trouverait alors dans le whatever:name-space-1.0 namespace plutôt que d'être dans aucun namespace. Si c'est ce que vous voulez, vous devez créer l'élément dans cet espace de noms:

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

Si vous voulez que le <loner> élément ne se trouvant dans aucun espace de noms, le XML produit est exactement ce dont vous avez besoin, et vous ne devriez pas vous soucier de l'attribut xmlns qui a été ajouté automatiquement pour vous.

10
JeniT

Étant donné que root se trouve dans un espace de noms non préfixé, tout enfant de root qui souhaite ne pas être à espace de noms doit être généré comme votre exemple. La solution serait de préfixer l'élément racine comme ceci:

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

Si possible, créez une classe de sérialisation puis procédez comme suit:

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

C'est plus sûr et vous pouvez contrôler les espaces de noms avec des attributs si vous avez vraiment besoin de plus de contrôle.

0
ilitirit

J'ai résolu le problème en utilisant le modèle d'usine. J'ai créé une fabrique pour les objets XElement. Comme paramètre pour l'instanciation de la fabrique, j'ai spécifié un objet XNamespace. Ainsi, chaque fois qu'un XElement est créé par l'usine, l'espace de noms sera ajouté automatiquement. Voici le code de l'usine:

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
brinke

Oui, vous pouvez empêcher XMLNS de XmlElement. Créer d'abord le temps qui vient: comme ça

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

Modifiez le code: et passez un espace de noms xml comme celui-ci

Code C #:

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