2009-11-24 4 views
16

Je travaille contre une api xml tierce partie. Ils ont défini une structure xml requise similaire à la suivante.xml nom d'élément avec deux-points

<ns1:E xmlns:ns1="schema"> 
<ns1:B> 
    <ns2:S> 
     <ns2:V> 
      <ns2:Bl /> 
     </ns2:V> 
    </ns2:S> 
</ns1:B> 
</ns1:E> 

Il existe une table SQL avec les informations que je dois mettre dans ce format xml. J'ai un adaptateur LINQ to SQL pour obtenir les données et j'utilise un System.Xml pour créer un document XML.

XmlDocument.CreateElement("ns1:E"); etc 

Cela fonctionne très bien tant que je supprime les deux-points des noms d'éléments. Avec les deux points, seul le côté droit du colon est dans le nom de l'élément. Je sais que les deux-points sont un non-non mais je n'ai aucun contrôle sur ce que l'api de 3ème partie dicte.

Quelles sont mes options pour contourner ce problème? Existe-t-il des moyens utiles de forcer les deux-points dans les noms des éléments? Je n'ai pas besoin d'utiliser XMLDocument mais je ne suis pas sûr de savoir quelle autre méthode m'apportera. MISE À JOUR: Je me rends compte que <ns1: fait référence à un espace de noms. Et oui, il y a 2. Lors de l'écriture sur le XML, je peux le faire fonctionner si je dis -

XmlDocument.CreateElement(ns1:E", "http://schema); 

Cependant, la sortie XML de c'est

<ns1:E xmlns:ns1="http://schema"> 

Si je dis simplement XmlDocument.CreateElement("ns1:E"); avec pas d'uri, alors la sortie est juste <E>. Je ne veux pas que la sortie ait la référence de schéma mais j'ai besoin d'avoir le préfixe. Le résultat que je veux atteindre est simplement <ns1:E>. Les deux namspaces sont déclarés en haut, ce qui signifierait que je devrais les déclarer à chaque nœud.

Répondre

0

Le mot précédant le signe deux-points est l'espace de nom. Si vous voulez avoir un élément "ns1: E", vous devez créer un élément nommé "E" et définir son espace de noms à "ns1". Les deux-points indiquent que ces éléments sont dans le ns1 namespace

+0

Merci, c'est logique mais d'une manière ou d'une autre je n'obtiens pas le résultat que je cherche encore. Pas certain de pourquoi. Si je spécifie une référence uri ou ns, le nom de l'élément est correct mais il ajoute la référence à la sortie que je ne veux pas. Si ce n'est pas le cas, le préfixe n'est pas ajouté. – nelsonwebs

5

Ceci est nécessaire lorsque vous utilisez plusieurs schémas. En supposant que le document n'utilise que ns1, cela équivaut essentiellement à ne pas avoir de "ns1:" dans ces balises. Voir this guide pour plus d'informations.

+3

En fait, ces deux-points indiquent que les éléments sont dans l'espace de noms 'schema'. 'ns1' n'est pas l'espace de noms; c'est l'abréviation de l'espace de noms. Cela peut changer le nom de l'espace de noms ne peut pas - pas sans devenir un espace de noms différent. –

5

Le document XML que vous avez publié n'est pas en réalité bien formé, parce que l'abréviation ns2 attribué à plusieurs des éléments est pas associé à un espace de noms.Fixe, il pourrait ressembler à ceci:

<ns1:E xmlns:ns1="schema" xmlns:ns2="my-namespace"> 
    <ns1:B> 
    <ns2:S> 
     <ns2:V> 
     <ns2:Bl /> 
     </ns2:V> 
    </ns2:S> 
    </ns1:B> 
</ns1:E> 

Le document XML ci-dessus est sémantiquement équivalent à celui-ci:

<s:E xmlns:s="schema"> 
    <s:B> 
    <S xmlns="my-namespace"> 
     <m:V xmlns:m="my-namespace"> 
     <s:Bl xmlns:s="my-namespace"/> 
     </m:V> 
    </S> 
    </s:B> 
</s:E> 

Et celui-ci:

<E xmlns="schema"> 
    <B xmlns="schema"> 
    <S xmlns="my-namespace"> 
     <V> 
     <Bl/> 
     </V> 
    </S> 
    </B> 
</E> 

Dans les trois cas, les éléments E et B sont dans l'espace de noms schema, tandis que les éléments S, V et Bl sont e dans l'espace de noms my-namespace.

Les préfixes d'espace de noms sont utiles, mais strictement parlant, ils sont inutiles. Vous pouvez créer des documents XML, comme le dernier exemple, qui n'utilisent aucun préfixe et qui déclarent explicitement l'espace de noms pour chaque élément.

Si, dans le traitement XML, vous pensez que vous vous souciez du préfixe d'un élément donné, vous avez certainement tort. La seule chose qui vous intéresse est l'espace de noms auquel il appartient. Par exemple, si je charge toute de ces trois documents dans un XmlDocument, le code suivant écrira l'élément « Bl »:

XmlNamespaceManager ns = new XmlNamespaceManager(d.NameTable); 
    ns.AddNamespace("a", "schema"); 
    ns.AddNamespace("b", "my-namespace"); 
    Console.Write(d.SelectSingleNode("/a:E/a:B/b:S/b:V/b:Bl", ns).OuterXml); 

Quand vous dites:

Je ne Je veux que la sortie ait la référence du schéma mais j'ai besoin d'avoir le préfixe. Le résultat que je veux atteindre est simplement <ns1:E>.

vous êtes presque certainement dans l'erreur. Un élément dont la balise est ns1:E n'a de sens que si le préfixe ns1 est mappé à un espace de noms, dans cet élément ou dans l'un de ses ancêtres. (De plus, un espace de noms est pas une référence de schéma.) Si vous utilisez

CreateElement("ns1", "E", "schema"); 

pour créer l'élément, puis l'ajouter à un élément qui a déjà déclaré ns1 comme étant le préfixe de l'espace de noms schema, le DOM ajoutera l'élément sans la déclaration d'espace de noms, car dans ce contexte, il n'est pas nécessaire. Si ns1 n'est pas déclaré (ou est déclaré comme abréviant un espace de noms autre que schema), alors le DOM va coller une déclaration d'espace de noms sur l'élément ainsi que le préfixe.

tl; dr: Vous vous souciez des espaces de noms, pas des préfixes d'espaces de noms.

1

(Je sais que c'est une vieille question, mais je fais quelque chose d'équivalent et j'ai compris comment agiter le poulet mort pour le faire fonctionner.) Je le documente pour le retrouver plus tard.)

string myName = "foo"; 

string ns_local = root.GetNamespaceOfPrefix("local"); 
string ns_x = root.GetNamespaceOfPrefix("x"); 

System.Xml.XmlNode newNode = doc.CreateNode(System.Xml.XmlNodeType.Element, "local", "MyTag", ns_local); 

System.Xml.XmlNode attr = doc.CreateNode(System.Xml.XmlNodeType.Attribute, "Key", ns_x); 
attr.Value = myName; 
newNode.Attributes.SetNamedItem(attr); 

attr = doc.CreateNode(System.Xml.XmlNodeType.Attribute, "MyAttr", ""); 
attr.Value = myName; 
newNode.Attributes.SetNamedItem(attr); 

nodeToAppendTo.AppendChild(newNode); 

Cela me donne une étiquette qui ressemble

<local:MyTag x:Key="foo" MyAttr="foo" /> 
2
<ns1:E xmlns:ns1="schema"> 
    <ns1:B> 
     <ns2:S> 
     <ns2:V> 
      <ns2:Bl /> 
     </ns2:V> 
     </ns2:S> 
    </ns1:B> 
</ns1:E> 

Donc, pour obtenir la sortie comme ci-dessus en utilisant Créer XmlElement il pourrait être réalisé comme ci-dessous:

CreateElement("ns1","E", "schema"); 
CreateElement("ns1","B", "schema"); 
CreateElement("ns2","S", "schema"); 
CreateElement("ns2","V", "schema"); 
CreateElement("ns2","B1", "schema"); 

Ici, l'élément "E" est l'élément racine, donc il le préfixe avec "ns1" avec le schéma.

Comme tous les autres éléments mentionnés comme « B », « S », « V », « B1 » sont les enfants Éléments de « E » il préfixe avec le préfixe mentionné, mais ne pas affiche à nouveau le schéma de la Éléments enfants.

Et donc vous obtenez la sortie désirée comme ci-dessus avec le schéma dans l'élément racine et seulement le préfixe pour les éléments enfants.