2011-01-11 10 views
12

Ho il seguente codice diCome rimuovo gli spazi dei nomi da 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(); 

Allora posso fare

doc_.getDocumentElement(); 

e ottenere il mio primo elemento, ma il problema è invece di essere job l'elemento è tns:job.

so circa e hanno cercato di utilizzare:

dbFactory_.setNamespaceAware(true); 

ma che non è proprio quello che sto cercando, ho bisogno di qualcosa per eliminare completamente gli spazi dei nomi.

Qualsiasi aiuto sarebbe apprezzato, Grazie,

Josh

+0

Perché si vuole sbarazzarsi di namespace, invece – Tomalak

+0

Ho qualche codice legacy che non li supporta – Grammin

+1

Se si tratta di POS legacy, forse basta usare il brute-force stripping dei prefissi dei namespace, anche qualcosa di semplice come regexp potrebbe funzionare. Non è la strada giusta in generale, ma a volte le cazzate devono essere combattute con merda. :) – StaxMan

risposta

4

Per i nodi di elementi e attributi:

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

vi darà la parte locale del nome del nodo.

Vedi Node.getLocalName()

+0

Esiste comunque la possibilità di rimuoverli completamente dall'XML? O sono qui per restare? – Grammin

+2

Come hanno accennato Anon e Tomalak, non vuoi davvero eliminare le informazioni sullo spazio dei nomi dal tuo XML. Questa è una buona soluzione per il tuo caso particolare, ma lascerei intatte le informazioni sul namespace. –

3

Piuttosto che

dbFactory_.setNamespaceAware(true); 

Usa

dbFactory_.setNamespaceAware(false); 

Anche se sono d'accordo con Tomalak: in generale, gli spazi dei nomi sono più utile che dannoso. Perché non vuoi usarli?


Edit: questa risposta non risponde alla domanda del PO, che era come sbarazzarsi di namespace prefissi. RD01 ha fornito la risposta corretta a questo.

+0

@Grammin - così è il problema che stai ancora vedendo il * prefisso * quando usi un parser che non è a conoscenza dello spazio dei nomi? Se sì, allora guarda la risposta di RD01. – Anon

+0

Sì, era – Grammin

2

È può pre-processo di XML per rimuovere tutti gli spazi dei nomi, se si deve assolutamente farlo. Lo raccomando, poiché rimuovere gli spazi dei nomi da un documento XML è essenzialmente paragonabile alla rimozione degli spazi dei nomi da un framework di programmazione o da una libreria: si rischia di scontrarsi con il nome e si perde la capacità di distinguere tra elementi distinti una volta. Tuttavia, è il tuo funerale. ;-)

Questa trasformazione XSLT rimuove tutti gli spazi dei nomi da qualsiasi 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> 

Applicalo al documento XML. Gli esempi Java per fare una cosa del genere dovrebbero essere molti, anche su questo sito. Il documento risultante avrà esattamente la stessa struttura e lo stesso layout, solo senza spazi dei nomi.

8

Utilizzare la funzione Regex.Questo risolverà questo 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

L'uso delle espressioni regolari per rimuovere tutti gli spazi dei nomi non può essere una buona cosa, anche se questo codice funziona. –

1

Tomalak, una correzione del vostro XSLT (in 3 ° modello):

<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

La dimensione del XML di input ha anche bisogno di essere considerati quando si sceglie la soluzione. Per xml di grandi dimensioni, nella dimensione di ~ 100k, possibile se l'input proviene da un servizio Web, è necessario considerare anche le implicazioni della raccolta di dati inutili quando si manipola una stringa di grandi dimensioni. Prima usavamo String.replaceAll e causava frequenti OOM in produzione con una dimensione heap di 1.5G a causa del modo in cui replaceAll è implementato.

È possibile fare riferimento a http://app-inf.blogspot.com/2013/04/pitfalls-of-handling-large-string.html per i nostri risultati.

Non sono sicuro di come XSLT si occupa di oggetti String di grandi dimensioni, ma abbiamo finito per analizzare la stringa manualmente per rimuovere i prefissi in una analisi per evitare la creazione di ulteriori oggetti java di grandi dimensioni.

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

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

0

Invece di usare TransformerFactory e quindi chiamando trasforma su di esso (che è stato iniettando lo spazio dei nomi vuoto, ho trasformato come segue:

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