2012-06-21 15 views
5

Estoy creando un objeto de documento W3C utilizando un valor de cadena. Una vez que creé el objeto de documento, quiero agregar un espacio de nombre al elemento raíz de este documento. Aquí está mi código actual:Agregar espacio de nombres a un documento XML ya creado

Document document = builder.parse(new InputSource(new StringReader(xmlString))); 
document.getDocumentElement().setAttributeNS("http://com", "xmlns:ns2", "Test"); 
document.setPrefix("ns2"); 
TransformerFactory tranFactory = TransformerFactory.newInstance(); 
Transformer aTransformer = tranFactory.newTransformer(); 
Source src = new DOMSource(document); 
Result dest = new StreamResult(new File("c:\\xmlFileName.xml")); 
aTransformer.transform(src, dest); 

Lo que yo uso como entrada:

<product> 
    <arg0>DDDDDD</arg0> 
    <arg1>DDDD</arg1> 
</product> 

Lo que la salida debe ser similar:

<ns2:product xmlns:ns2="http://com"> 
    <arg0>DDDDDD</arg0> 
    <arg1>DDDD</arg1> 
</ns2:product> 

tengo que añadir el valor del prefijo y el espacio de nombres también la cadena xml de entrada. Si pruebo el código anterior obtengo esta excepción:

NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces. 

¡Apreciar tu ayuda!

+1

Es el espacio de nombres 'builder'-consciente? 'builder.isNamespaceAware()' – rolve

Respuesta

19

Dado que no existe una manera fácil de cambiar el nombre del elemento raíz, tendremos que reemplazarlo por un elemento que tenga el espacio de nombre y el atributo correctos, y luego copiar todos los elementos secundarios originales en él. No es necesario forzar la declaración del espacio de nombres porque al dar al elemento el espacio de nombre correcto (URI) y establecer el prefijo, la declaración será automática.

Vuelva a colocar la setAttribute y setPrefix con este (línea 2,3)

String namespace = "http://com"; 
String prefix = "ns2"; 
// Upgrade the DOM level 1 to level 2 with the correct namespace 
Element originalDocumentElement = document.getDocumentElement(); 
Element newDocumentElement = document.createElementNS(namespace, originalDocumentElement.getNodeName()); 
// Set the desired namespace and prefix 
newDocumentElement.setPrefix(prefix); 
// Copy all children 
NodeList list = originalDocumentElement.getChildNodes(); 
while(list.getLength()!=0) { 
    newDocumentElement.appendChild(list.item(0)); 
} 
// Replace the original element 
document.replaceChild(newDocumentElement, originalDocumentElement); 

En el código original del autor trató de declarar un espacio de nombres de elemento de la siguiente manera:

.setAttributeNS("http://com", "xmlns:ns2", "Test"); 

El primer parámetro es el espacio de nombres del atributo, y dado que es un atributo de espacio de nombres, debe tener el URI http://www.w3.org/2000/xmlns/. El espacio de nombres declarado debe entrar en la tercera parámetro

.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:ns2", "http://com"); 
+0

¡Muchas gracias! Realmente me ayudó, en mi caso el espacio de nombres nunca se ha incluido en el cálculo de resumen, porque lo agregué como un atributo regular en lugar de agregarlo como un espacio de nombres real. +1 – Springrbua

+0

Parece que este enfoque no puede agregar el mismo espacio de nombres al elemento hijo, por lo que utilizo este enfoque, luego genero cadena XML desde el documento y analizo cadena XML generada de nuevo. – wangf

0

enfoque de fuelle también trabaja para mí, pero probablemente no debería utilizar en caso crítico rendimiento.

  1. Agregue espacio de nombre para documentar el elemento raíz como atributo.
  2. Transformar el documento en cadena XML. El propósito de este paso es hacer que el elemento hijo en la cadena XML herede el espacio de nombres del elemento principal.
  3. Ahora la cadena xml tiene espacio de nombre.
  4. Puede utilizar la cadena XML para crear un documento nuevo o usado para JAXB unmarshal, etc.

private static String addNamespaceToXml(InputStream in) 
     throws ParserConfigurationException, SAXException, IOException, 
     TransformerException { 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    /* 
    * Must not namespace aware, otherwise the generated XML string will 
    * have wrong namespace 
    */ 
    // dbf.setNamespaceAware(true); 
    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document document = db.parse(in); 
    Element documentElement = document.getDocumentElement(); 
    // Add name space to root element as attribute 
    documentElement.setAttribute("xmlns", "http://you_name_space"); 
    String xml = transformXmlNodeToXmlString(documentElement); 
    return xml; 
} 

private static String transformXmlNodeToXmlString(Node node) 
     throws TransformerException { 
    TransformerFactory transFactory = TransformerFactory.newInstance(); 
    Transformer transformer = transFactory.newTransformer(); 
    StringWriter buffer = new StringWriter(); 
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
    transformer.transform(new DOMSource(node), new StreamResult(buffer)); 
    String xml = buffer.toString(); 
    return xml; 
} 
Cuestiones relacionadas