2011-01-11 6 views
12

que tienen el código¿Cómo elimino los espacios de nombres de xml, usando java dom?

DocumentBuilderFactory dbFactory_ = DocumentBuilderFactory.newInstance(); 
Document doc_; 
DocumentBuilder dBuilder = dbFactory_.newDocumentBuilder(); 
StringReader reader = new StringReader(s); 
InputSource inputSource = new InputSource(reader); 
doc_ = dBuilder.parse(inputSource); 
doc_.getDocumentElement().normalize(); 

siguiente Entonces puedo hacer

doc_.getDocumentElement(); 

y conseguir mi primer elemento, pero el problema es en lugar de ser el elemento job es tns:job.

me conocen y han tratado de usar:

dbFactory_.setNamespaceAware(true); 

pero eso no es justo lo que estoy buscando, necesito algo para deshacerse completamente de espacios de nombres.

Cualquier ayuda se agradece, Gracias,

Josh

+0

¿Por qué quiere deshacerse de espacios de nombres, en lugar de lidiar con ellos? – Tomalak

+0

Tengo un código heredado que no los admite. – Grammin

+1

Si se trata de un POS heredado, tal vez solo use la fuerza bruta para eliminar los prefijos del espacio de nombres, incluso algo tan simple como la expresión regular funcionaría. No es el camino correcto en general, pero a veces se debe luchar con mierda :) – StaxMan

Respuesta

4

Para los nodos de elementos y atributos:

Node node = ...; 
String name = node.getLocalName(); 

le dará la parte local del nombre del nodo.

Ver Node.getLocalName()

+0

¿Hay alguna forma de eliminarlos por completo del xml? ¿O están aquí para quedarse? – Grammin

+2

Como han mencionado Anon y Tomalak, realmente no desea quitar información de espacios de nombres de su XML. Esta es una buena solución para su caso particular, pero dejaría la información del espacio de nombres intacta. –

3

En lugar de

dbFactory_.setNamespaceAware(true); 

Uso

dbFactory_.setNamespaceAware(false); 

Aunque estoy de acuerdo con Tomalak: en general, los espacios de nombres son más útil que dañino. ¿Por qué no quieres usarlos?


Editar: esta respuesta no responde a la pregunta de la OP, que era la manera de deshacerse de espacio de nombres prefijos. RD01 proporcionó la respuesta correcta a eso.

+0

@Grammin - ¿así que sigue viendo el * prefijo * cuando usa un analizador que no es consciente del espacio de nombres? En caso afirmativo, mire la respuesta de RD01. – Anon

+0

Sí, eso fue – Grammin

2

Usted puede pre-proceso de XML para eliminar todos los espacios de nombres, si es absolutamente necesario hacerlo. Lo recomendaría en contra, ya que eliminar espacios de nombres de un documento XML es en esencia comparable a eliminar espacios de nombres de un marco de programación o una biblioteca: arriesga los conflictos de nombres y pierde la capacidad de diferenciar entre elementos distintos una vez. Sin embargo, es tu funeral. ;-)

Esta transformación XSLT elimina todos los espacios de nombres de cualquier documento XML.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:element> 
    </xsl:template> 

    <xsl:template match="@*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

Utilícela en su documento XML. Los ejemplos de Java para hacer tal cosa deberían ser suficientes, incluso en este sitio. El documento resultante tendrá exactamente la misma estructura y diseño, sin espacios de nombres.

8

Utilice la función Regex.Esto va a resolver este problema:

public static String removeXmlStringNamespaceAndPreamble(String xmlString) { 
    return xmlString.replaceAll("(<\\?[^<]*\\?>)?", ""). /* remove preamble */ 
    replaceAll("xmlns.*?(\"|\').*?(\"|\')", "") /* remove xmlns declaration */ 
    .replaceAll("(<)(\\w+:)(.*?>)", "$1$3") /* remove opening tag prefix */ 
    .replaceAll("(</)(\\w+:)(.*?>)", "$1$3"); /* remove closing tags prefix */ 
} 
+19

Usar expresiones regulares para eliminar todos los espacios de nombres simplemente no puede ser una buena cosa, incluso si este código funciona. –

1

Tomalak, uno de arreglo del XSLT (en la tercera plantilla):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="node() | @*" /> 
    </xsl:element> 
    </xsl:template> 

    <xsl:template match="@*"> 
    <!-- Here! --> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*" /> 
    </xsl:copy> 

    </xsl:template> 
</xsl:stylesheet> 
1

El tamaño del xml de entrada también debe tenerse en cuenta al elegir la solución. Para xmls grandes, en el tamaño de ~ 100k, es posible si su entrada es de un servicio web, también debe tener en cuenta las implicaciones de recolección de basura cuando manipula una cadena grande. Utilizamos String.replaceAll antes, y causó OOM frecuente en la producción con un tamaño de almacenamiento dinámico de 1,5G debido a la forma en que se implementó replaceAll.

Puede hacer referencia a http://app-inf.blogspot.com/2013/04/pitfalls-of-handling-large-string.html para nuestros hallazgos.

No estoy seguro de cómo XSLT trata con objetos String grandes, pero terminamos analizando manualmente la cadena para eliminar prefijos en un análisis sintáctico para evitar crear objetos java grandes adicionales.

public static String removePrefixes(String input1) { 
    String ret = null; 
    int strStart = 0; 
    boolean finished = false; 
    if (input1 != null) { 
     //BE CAREFUL : allocate enough size for StringBuffer to avoid expansion 
     StringBuffer sb = new StringBuffer(input1.length()); 
     while (!finished) { 

      int start = input1.indexOf('<', strStart); 
      int end = input1.indexOf('>', strStart); 
      if (start != -1 && end != -1) { 
       // Appending anything before '<', including '<' 
       sb.append(input1, strStart, start + 1); 

       String tag = input1.substring(start + 1, end); 
       if (tag.charAt(0) == '/') { 
        // Appending '/' if it is "</" 
        sb.append('/'); 
        tag = tag.substring(1); 
       } 

       int colon = tag.indexOf(':'); 
       int space = tag.indexOf(' '); 
       if (colon != -1 && (space == -1 || colon < space)) { 
        tag = tag.substring(colon + 1); 
       } 
       // Appending tag with prefix removed, and ">" 
       sb.append(tag).append('>'); 
       strStart = end + 1; 
      } else { 
       finished = true; 
      } 
     } 
     //BE CAREFUL : use new String(sb) instead of sb.toString for large Strings 
     ret = new String(sb); 
    } 
    return ret; 
} 
2
public static void wipeRootNamespaces(Document xml) {  
    Node root = xml.getDocumentElement(); 
    NodeList rootchildren = root.getChildNodes(); 
    Element newroot = xml.createElement(root.getNodeName()); 

    for (int i=0;i<rootchildren.getLength();i++) { 
     newroot.appendChild(rootchildren.item(i).cloneNode(true)); 
    } 

    xml.replaceChild(newroot, root); 
} 
+0

línea # 4 ... root.getLocalName(); (?) –

0

En lugar de utilizar TransformerFactory y luego llamar a transformar en él (que se inyectará el espacio de nombres vacío, que transforma la manera siguiente:

OutputStream outputStream = new FileOutputStream(new File(xMLFilePath)); 
    OutputFormat outputFormat = new OutputFormat(doc, "UTF-8", true); 
    outputFormat.setOmitComments(true); 
    outputFormat.setLineWidth(0); 

    XMLSerializer serializer = new XMLSerializer(outputStream, outputFormat); 
    serializer.serialize(doc); 
    outputStream.close(); 
Cuestiones relacionadas