Question

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

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>

Sortie souhaitée :

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

Existe-t-il une solution applicable au code XmlDocument, et non quelque chose qui se produit après que convertisse le document en chaîne avec OuterXml?

Mon raisonnement est de voir si je peux correspondre au XML standard d'un protocole particulier en utilisant XML généré par XmlDocument. L'attribut <=> vide peut ne pas briser ou perturber un analyseur, mais il n'est également présent dans aucun des usages de ce protocole que j'ai vus.

Était-ce utile?

La solution

Grâce à la réponse de Jeremy Lew et à un peu plus de jeu, j'ai découvert comment supprimer les xmlns attributs vierges: transmettez l'espace de noms du nœud racine lors de la création de tout nœud enfant que vous ne voulez pas . un préfixe sur. Utiliser 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 ne puissent pas non plus avoir 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!

Autres conseils

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

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

Ceci élimine le besoin de copier ou de répéter l'espace de noms partout.

Si l'élément <loner> de votre exemple XML ne contenait pas la déclaration d'espace de noms xmlns par défaut, il se trouverait dans l'espace de noms whatever:name-space-1.0 plutôt que dans aucun espace de noms. 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 souhaitez que l'élément <=> ne soit dans aucun espace de nom, le code XML généré correspond exactement à vos besoins et vous ne devez pas vous inquiéter de l'attribut <=> qui a été ajouté automatiquement pour vous.

Puisque la racine est dans un espace de noms non préfixé, tout enfant de la racine qui veut être non-namespaced doit être généré comme dans votre exemple. La solution serait de préfixer l’élément racine comme suit:

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

Si possible, créez une classe de sérialisation puis faites:

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.

J'ai résolu le problème en utilisant le modèle d'usine. J'ai créé une usine pour les objets XElement. En tant que paramètre pour l'instanciation de la fabrique, j'ai spécifié un objet XNamespace. Ainsi, chaque fois qu'un XElement est créé par la fabrique, l'espace de nom 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);
    }
}

Oui, vous pouvez empêcher XMLNS de XmlElement. Première heure de création: 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 l'espace de noms xml comme ça

Code C #:

XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1");
bookElement.SetAttribute("lat", "30.53597");
bookElement.SetAttribute("lon", "97.753324");
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top