2011-01-11 12 views
12

Mam następujący kodJak usunąć przestrzenie nazw z xml, używając 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(); 

Wtedy mogę zrobić

doc_.getDocumentElement(); 

i dostać mój pierwszy element, ale problemem jest to, zamiast job element jest tns:job.

Znam i próbowali użyć:

dbFactory_.setNamespaceAware(true); 

ale to po prostu nie to, czego szukam, muszę coś całkowicie pozbyć się nazw.

Każda pomoc będzie mile widziane, Dzięki

Josh

+0

Dlaczego chcesz pozbyć się nazw, zamiast radzenia sobie z nimi? – Tomalak

+0

Mam trochę starszego kodu, który ich nie obsługuje – Grammin

+1

Jeśli jest to starszy POS, może po prostu użyjesz brutalnego usuwania z prefiksów przestrzeni nazw, nawet coś tak prostego jak regexp zadziała. w ogóle, ale czasami bzdury należy zwalczać z gównem. :) – StaxMan

Odpowiedz

4

Dla elementów i atrybutów węzłów:

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

daje lokalną część nazwy węzła.

Zobacz Node.getLocalName()

+0

Czy mimo to całkowicie usunąć je z xml? Czy mogą tu zostać? – Grammin

+2

Jak wspomnieli Anon i Tomalak, naprawdę nie chcecie rozebrać informacji o przestrzeni nazw ze swojego XML. Jest to dobre obejście dla konkretnego przypadku, ale pozostawiłbym informację o przestrzeni nazw nienaruszoną. –

3

Zamiast

dbFactory_.setNamespaceAware(true); 

Zastosowanie

dbFactory_.setNamespaceAware(false); 

Chociaż zgadzam się z Tomalak: w ogóle, przestrzenie nazw są bardziej pomocne niż szkodliwe. Dlaczego nie chcesz ich użyć?


Edit: ta odpowiedź nie jest odpowiedź na pytanie OP, który był, jak się pozbyć nazw przedrostków. RD01 dostarczyło poprawną odpowiedź na to.

+0

@Grammin - tak jest problem, że nadal widzisz * przedrostek *, gdy używasz parsera, który nie jest świadomy przestrzeni nazw? Jeśli tak, to spójrz na odpowiedź RD01. – Anon

+0

Tak, to było to – Grammin

2

You może wstępnie proces XML, aby usunąć wszystkie obszary nazw, jeśli absolutnie muszą zrobić. Polecam przeciwko niemu, ponieważ usuwanie przestrzeni nazw z dokumentu XML jest w istocie porównywalne do usuwania przestrzeni nazw ze struktury programistycznej lub biblioteki - ryzykujesz konfliktami nazw i tracisz możliwość rozróżniania elementów niegdyś odrębnych. Jest to jednak twój pogrzeb. ;-)

Ta transformacja XSLT usuwa wszystkie przestrzenie nazw z dowolnego dokumentu 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> 

Zastosuj go do dokumentu XML. Przykłady Java do robienia takich rzeczy powinny być dużo, nawet na tej stronie. Wynikowy dokument będzie dokładnie tej samej struktury i układu, tylko bez przestrzeni nazw.

8

Użyj funkcji Regex.To rozwiąże ten 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

Użycie wyrażeń regularnych w celu usunięcia wszystkich przestrzeni nazw po prostu nie może być dobrą rzeczą, nawet jeśli ten kod działa. –

1

Tomalak, jedną poprawkę swojego XSLT (w 3 szablonu):

<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

Wielkość xml wejściowego należy również uwzględnić przy wyborze rozwiązania. W przypadku dużych xml, w rozmiarze ~ 100k, jeśli twoje dane wejściowe pochodzą z usługi sieciowej, musisz również wziąć pod uwagę konsekwencje zbierania śmieci podczas manipulowania dużym ciągiem znaków. Użyliśmy wcześniej String.replaceAll i spowodowało to często OOM w produkcji z wielkością sterty 1,5G ze względu na sposób implementacji replaceAll.

Możesz zapoznać się z http://app-inf.blogspot.com/2013/04/pitfalls-of-handling-large-string.html dla naszych wyników.

Nie jestem pewien, w jaki sposób XSLT radzi sobie z dużymi obiektami typu String, ale skończyliśmy analizować ciąg ręcznie w celu usunięcia prefiksów w jednym analizie, aby uniknąć tworzenia dodatkowych dużych obiektów java.

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

wiersz nr 4 ... root.getLocalName(); (?) –

0

Zamiast TransformerFactory a następnie wywołanie przekształcić na niej (co było wstrzykiwanie pustą przestrzeń nazw, I przekształcił się następująco:

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(); 
Powiązane problemy