www w3schools w3school page certified certification browsers bootstrap asp javascript google-chrome xmlserializer

javascript - w3schools - Chrome 22 genera XML no válido cuando los atributos tienen un espacio de nombres xlink



www w3schools com browsers default asp (1)

Todavía estoy bastante seguro de que hay un error en el XMLSerializer de Chrome, probablemente introducido al abordar el manejo de SVG de los atributos XLink que Barbarrosa señaló . Pero dada la falta de respuesta al informe de error que hice, tuvimos que avanzar y solucionar el problema.

Resolvemos el problema llamando a esta función en el elemento de documentElement :

function EnsureXLinkNamespaceOnElement(element) { if (element.nodeType == 1) { var usesXLinkNamespaceUri = false; var hasXLinkNamespacePrefixDefined = false; for (var i = 0; i < element.attributes.length; i++) { var attribute = element.attributes[i]; if (attribute.specified) { if (attribute.name.indexOf("xmlns:xlink") == 0) { hasXLinkNamespacePrefixDefined = true; } else if (attribute.namespaceURI == "http://www.w3.org/1999/xlink") { usesXLinkNamespaceUri = true; } } } if (usesXLinkNamespaceUri && !hasXLinkNamespacePrefixDefined) { element.setAttribute(''xmlns:xlink'', ''http://www.w3.org/1999/xlink''); } for (i = 0; i < element.childNodes.length; i++) { EnsureXLinkNamespaceOnElement(element.childNodes[i]); } } }

La función simplemente garantiza que el atributo xmlns:xlink se declara en cualquier elemento que se haya atribuido en el espacio de nombres XLink. Como la función atraviesa el árbol y, por lo tanto, puede llevar bastante tiempo, solo lo invoco para las versiones de Chrome 22 y superiores.

Tenga en cuenta que en la mayoría de los casos, también puede salirse con la simple adición de los espacios de nombres xmlns:xlink en el elemento del documento, ya que se heredará de allí. Pero en nuestro caso hubo otro código que elimina el elemento del documento con una expresión regular, por lo que decidimos jugarlo de forma segura y simplemente agregar el atributo donde sea necesario.

Actualización (20130324):

El bug se solucionó y verificó en Chrome Canary 26. También he podido verificarlo en la versión 25.0.1364.172 m .

Tengo el siguiente fragmento de JavaScript mínimo:

var xml = ''<El a:title="T" a:href="H" xmlns:a="http://www.w3.org/1999/xlink" />''; var dom = new DOMParser().parseFromString(xml, ''text/xml''); xml = new XMLSerializer().serializeToString(dom);

Cuando ejecuto el código en la mayoría de los navegadores (solo péguelo en la consola de JavaScript de su navegador), el XML analizado y luego serializado es equivalente al original. Por ejemplo en Chrome 8 obtengo:

<El xmlns:a="http://www.w3.org/1999/xlink" a:title="T" a:href="H"/>

Sin embargo, en Chrome 22, el mismo fragmento de código cambia el XML a:

<El xmlns:a="http://www.w3.org/1999/xlink" xlink:title="T" xlink:href="H"/>

Tenga en cuenta que el prefijo xlink del espacio de nombres utilizado por el título y los atributos href no está definido en ninguna parte, por lo que el XML ahora no es válido. Como probablemente pueda imaginar, esto causa todo tipo de problemas para el código que intenta utilizar posteriormente el XML.

¿Se trata de un error en el XMLSerializer o me faltan algunas complejidades acerca de cómo se debe serializar el DOM?

¿Alguien también encontró una solución alternativa que pueda poner en código, en lugar de hacer que el XML coincida con la preferencia aparente de usar xlink como el prefijo para el espacio de nombres XLink?

Actualizar

Hice algunas pruebas adicionales y el problema parece deberse al hecho de que el XMLSerializer reconoce el espacio de nombres XLink e insiste en que se le envíe un prefijo xlink , sin registrar correctamente ese prefijo.

Así que este fragmento funciona bien:

var xml = ''<El a:title="T" a:href="H" xmlns:a="any-other-namespace-uri" />''; var dom = new DOMParser().parseFromString(xml, ''text/xml''); xml = new XMLSerializer().serializeToString(dom);

Así que aquí cambié la URL del espacio de nombres a algo menos conocido y la salida ahora es válida:

<El xmlns:a="any-other-namespace-uri" a:title="T" a:href="H"/>

El siguiente fragmento también funciona bien:

var xml = ''<El a:title="T" a:href="H" xmlns:a="http://www.w3.org/2000/xlink" />''; var dom = new DOMParser().parseFromString(xml, ''text/xml''); xml = new XMLSerializer().serializeToString(dom);

Entonces, en este caso, usamos el prefijo "esperado" para el espacio de nombres XLink y luego se serializa sin problemas:

<El xmlns:a="http://www.w3.org/2000/xlink" a:title="T" a:href="H"/>