2011-01-11 15 views
12

Ich habe den folgenden CodeWie entferne ich Namespaces von XML mit 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(); 

Dann kann ich

doc_.getDocumentElement(); 

tun und mein erstes Element erhalten, aber das Problem ist, statt job des Seins das Element tns:job ist.

Ich kenne und haben zu verwenden versucht:

dbFactory_.setNamespaceAware(true); 

aber das ist einfach nicht, was ich suche, ich brauche ganz etwas von Namensräumen loszuwerden.

Jede Hilfe würde geschätzt, Danke,

Josh

+0

Warum wollen Sie von Namespaces, um loszuwerden, anstatt ? mit ihnen fertig zu – Tomalak

+0

habe ich einig Legacy-Code, die sie nicht unterstützt – Grammin

+1

Wenn es Legacy-PO ist, vielleicht nur Brute-Force verwendet aus Namespacepräfixe Strippen;.. auch etwas so einfach wie regexp funktionieren würde, es ist nicht der richtige Weg im Allgemeinen, aber manchmal Mist ist zu kämpfen mit Mist. :) – StaxMan

Antwort

4

Für Element- und Attributknoten:

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

geben Sie den lokalen Teil des Namens des Knotens.

Siehe Node.getLocalName()

+0

Gibt es sowieso, sie vollständig aus dem XML zu entfernen? Oder sind sie hier, um zu bleiben? – Grammin

+2

Wie Anon und Tomalak bereits erwähnt haben, möchten Sie Namespace-Informationen aus Ihrem XML-Dokument nicht entfernen. Dies ist ein guter Workaround für Ihren speziellen Fall, aber ich würde die Namespace-Informationen intakt lassen. –

3

Statt

dbFactory_.setNamespaceAware(true); 

Verwenden

dbFactory_.setNamespaceAware(false); 

Obwohl ich mit Tomalak einig: in der Regel Namensräume sind hilfreicher als schädlich. Warum willst du sie nicht benutzen?


Edit: diese Antwort keine Antwort auf die Frage des OP, das war, wie der NamespacePräfixe loszuwerden. RD01 lieferte dazu die richtige Antwort.

+0

@Grammin - so ist das Problem, dass Sie immer noch das * Präfix * sehen, wenn Sie einen Parser verwenden, der kein Namespace ist? Wenn ja, dann schauen Sie sich die Antwort von RD01 an. – Anon

+0

Ja, das war es – Grammin

2

Sie können Vorprozess XML alle Namensraum zu entfernen, wenn Sie unbedingt tun müssen. Ich würde dagegen empfehlen, da das Entfernen von Namespaces aus einem XML-Dokument im Wesentlichen mit dem Entfernen von Namespaces aus einem Programmier-Framework oder einer Bibliothek vergleichbar ist - Sie riskieren Namenskonflikte und verlieren die Fähigkeit, zwischen einmal getrennten Elementen zu unterscheiden. Es ist jedoch deine Beerdigung. ;-)

Diese XSLT-Umwandlung entfernt alle Namespaces aus einem XML-Dokument.

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

Wenden Sie es auf Ihr XML-Dokument an. Java-Beispiele für so etwas sollten auch auf dieser Seite reichlich vorhanden sein. Das resultierende Dokument hat genau die gleiche Struktur und das gleiche Layout, nur ohne Namespaces.

8

Verwenden Sie die Regex-Funktion.Dies löst dieses Problem:

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

Die Verwendung von Regexes zum Entfernen aller Namespaces kann einfach nicht gut sein, auch wenn dieser Code funktioniert. –

1

Tomalak, ein Update Ihrer XSLT (in der 3. Vorlage):

<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

Die Größe des Eingangs xml muss auch berücksichtigt werden, wenn die Lösung der Wahl. Bei großen xmls in der Größe ~ 100k, die möglich sind, wenn Ihre Eingabe von einem Webdienst stammt, müssen Sie auch die Auswirkungen der Speicherbereinigung berücksichtigen, wenn Sie eine große Zeichenfolge bearbeiten. Wir haben zuvor String.replaceAll verwendet und aufgrund der Implementierung von replaceAll häufiges OOM in der Produktion mit einer 1,5G-Heap-Größe verursacht.

können Sie http://app-inf.blogspot.com/2013/04/pitfalls-of-handling-large-string.html für unsere Ergebnisse verweisen.

Ich bin mir nicht sicher, wie XSLT große String-Objekte behandelt, aber wir haben die Zeichenfolge manuell analysiert, um Präfixe in einem Parse zu entfernen, um das Erstellen zusätzlicher großer Java-Objekte zu vermeiden.

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

Zeile # 4 ... root.getLocalName(); (?) –

0

Statt TransformerFactory verwenden und dann forderte sie auf, Transformation (die den leeren Namensraum wurde die Injektion, transformiert ich wie folgt:

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