guia factura electronica .net xml namespaces linq-to-xml

.net - guia factura electronica



Nombre del elemento xml con dos puntos (6)

(Sé que es una pregunta antigua, pero estoy haciendo algo equivalente y descubrí cómo agitar al pollo muerto para que funcione. Lo estoy documentando para poder encontrarlo más adelante).

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

Esto me da una etiqueta que parece

<local:MyTag x:Key="foo" MyAttr="foo" />

Estoy trabajando en contra de un api xml de terceros. Han definido una estructura xml requerida similar a la siguiente.

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

Hay una tabla SQL con la información que necesito poner en este formato XML. Tengo un adaptador LINQ to SQL para obtener los datos y estoy usando un System.Xml para crear un documento XML.

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

Esto funciona bien siempre que elimine los dos puntos de los nombres de los elementos. Con los dos puntos, solo el lado derecho de los dos puntos está en el nombre del elemento. Sé que los dos puntos son un no-no, pero no tengo ningún control sobre lo que dicta la API de terceros.

¿Cuáles son mis opciones para solucionar esto? ¿Hay alguna forma útil de forzar a los dos puntos en los nombres de los elementos? No tengo que usar XMLDocument pero no estoy seguro de qué otro método me llevará allí.

ACTUALIZACIÓN: Me doy cuenta de que <ns1: refiere a un espacio de nombres. Y sí, hay 2. Al escribir el XML, puedo hacer que funcione si digo:

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

Sin embargo, la salida XML de esto es

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

Si acabo de decir XmlDocument.CreateElement("ns1:E"); sin uri, entonces la salida es solo <E> . No quiero que la salida tenga la referencia del esquema, pero sí necesito el prefijo. El resultado que quiero lograr es simplemente <ns1:E> . Ambos espacios de nombres se declaran en la parte superior, lo que creo que significaría que tendría que declararlos en cada nodo.


El documento XML que publicó no está realmente bien formado, porque la abreviatura ns2 asignada a muchos de los elementos no está asociada con un espacio de nombres. Arreglado, podría verse así:

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

El documento XML anterior es semánticamente equivalente a este:

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

Y a éste:

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

En los tres casos, los elementos E y B están en el espacio schema nombres del schema , mientras que los elementos S , V y Bl están en el my-namespace nombres my-namespace namespace.

Los prefijos de espacio de nombres son útiles, pero estrictamente hablando son innecesarios. Puede crear documentos XML, como el último ejemplo, que no utilizan prefijos y que declaran el espacio de nombres explícitamente para cada elemento.

Si, al procesar XML, cree que le importa qué prefijo utiliza un elemento determinado, es casi seguro que esté equivocado. Lo único que te importa es a qué espacio de nombres pertenece. Por ejemplo, si cargo cualquiera de esos tres documentos en un XmlDocument , el siguiente código escribirá el elemento ''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);

Cuando tu dices:

No quiero que la salida tenga la referencia del esquema, pero sí necesito el prefijo. El resultado que quiero lograr es simplemente <ns1:E> .

Casi seguro que estás en el error. Un elemento cuya etiqueta es ns1:E tiene sentido a menos que el prefijo ns1 se ns1 a un espacio de nombres, ya sea en ese elemento o en uno de sus antepasados. (Además, un espacio de nombres no es una referencia de esquema.) Si usa

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

para crear el elemento y luego agregarlo a un elemento que ya haya declarado ns1 como el prefijo para el espacio schema nombres de schema , luego el DOM agregará el elemento sin la declaración de espacio de nombres, porque en ese contexto no es necesario. Si ns1 no se declara (o se declara que abrevia un espacio de nombres distinto del schema ), el DOM pegará una declaración de espacio de nombres en el elemento, así como el prefijo.

tl; dr: le interesan los espacios de nombres, no los prefijos de espacios de nombres.



La palabra antes de los dos puntos es el espacio de nombres. Si desea tener un elemento "ns1: E", necesita crear un elemento llamado "E" y establecer su espacio de nombres en "ns1".


Los dos puntos indican que esos elementos están en el namespace ns1. Esto es necesario cuando está utilizando múltiples esquemas. Suponiendo que el documento solo usa ns1, es esencialmente equivalente a no tener ningún "ns1:" en esas etiquetas. Vea esta guía para más información.


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

Por lo tanto, para obtener el resultado anterior utilizando Crear XmlElement se podría lograr de la siguiente manera:

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

Aquí el elemento "E" es el elemento raíz, de modo que lo prefija con "ns1" junto con el esquema.

Dado que todos los demás elementos mencionados como "B", "S", "V", "B1" son elementos secundarios de "E", prefije con el prefijo mencionado pero no muestra nuevamente el esquema de los elementos secundarios.

Y, por lo tanto, obtiene el resultado deseado como el anterior con el esquema en el elemento raíz y solo el prefijo para los elementos secundarios.