2017-07-07 1 views
2

Ich muss XML-Transformation mit SAX-Parser tun, dafür muss ich Namespace aus dem XML entfernen. Da wir mit großem XML umgehen, muss ich den SAX Parser verwenden.Wie Xml Namesapce mit SAX-Parser zu entfernen

XML-Beispieleingabe:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" 
xmlns:ns2="http://www.google.com/generation/type"> 
    <ns2:meta> 
     <gender xmlns="" xmlns:ns5="http://www.google.com/generation">M</gender> 
     <dateOfBirth xmlns="" xmlns:ns5="http://www.google.com/generation">1976-07-19</dateOfBirth> 
     <ns2:languageRef>ENG</ns2:languageRef> 
    </ns2:meta> 
    <root> 

mit Hilfe von SAX-Parser, ich brauche die unten ausgegeben.

 <root> 
      <meta> 
       <gender>M</gender> 
       <dateOfBirth>1976-07-19</dateOfBirth> 
       <languageRef>ENG</languageRef> 
      </ns2:meta> 
     <root> 

Vielen Dank im Voraus ..

Der Code, der ich versuchte,

i mit XMLFlterImpl versucht,

XMLReader xr = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) { 

    @Override 
    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { 

    if (qName.contains(":")) { 
     String[] data = data = qName.split(":"); 


     super.startElement(uri, localName, data[1], atts); 
    } else { 
     super.startElement(uri, localName, qName, atts); 
    } 
    } 

dies der Name des Elements Präfix (Namespace) entfernt, aber nicht sicher, wie die Namespace-Attribute zu entfernen

+0

müssen Sie SAX verwenden oder stattdessen StAX verwenden? – nandsito

+0

Mit Sax Parser nur – pradeep

+0

dürfen Sie StAX verwenden, um XML-Ausgabe zu schreiben, da SAX XML nicht schreibt? – nandsito

Antwort

1

EDIT:

Ok, mit Richtung von den Kommentaren von @MichaelKay, hier ist meine Antwort aktualisiert.

Um Namespace von Tags zu entfernen:

Wie in seiner Antwort vorgeschlagen, die startElement"" anstelle von uri haben sollte. Was ist mit Ending-Tag?: In Ihrer Frage verstehe ich nicht, warum Sie ns2 für die Endung meta Tag möchten, insbesondere wenn Sie es für das Start-Tag entfernen möchten. Ich nehme an, Sie möchten, dass es auch für End-Tags entfernt wird. So ähnlich endElement sollte auch "" anstelle von uri haben.

Filter XMLNS Attribute:

Sie könnten eine neue AttributesImpl erstellen. Dann gehen Sie durch die Liste der Attribute und überprüfen, ob die QName beginnt mit xmlns, wenn fügen Sie es nicht auf die AttributesImpl und verwenden Sie es in der startElement als:

super.startElement("", localName, data[1], aImpl);

Beachten Sie auch, dass nach @MartinHonnen, ja die Attribute 'uri sollte auch "" sein und auch die qName sollte ohne Präfix wie mit Elementen sein. Aber wenn Sie die Namen der Attribute als solche behalten möchten (was ich glaube nicht, dass Sie wollen), können Sie einfach atts.getQName(i) behalten, wie es ist.

auch Set-Namespaces verfügen auf false wie:

xf.setFeature("http://xml.org/sax/features/namespaces", false);

Code:

try { 

    InputSource file = new InputSource("filterns.xml"); 

    XMLFilterImpl xf = new XMLFilterImpl(
      XMLReaderFactory.createXMLReader()) { 
     @Override 
     public void startElement(String uri, String localName, 
      String qName, Attributes atts) throws SAXException { 

       AttributesImpl aImpl = new AttributesImpl(); 

       int l = atts.getLength(); 
       for (int i = 0; i < l; i++) { 

        if (atts.getQName(i) != null 
          && atts.getQName(i).startsWith("xmlns")) { 
         continue; 
        } else { 
         String aQName = atts.getQName(i); 
         String[] s = aQName.split(":"); 
         if (s.length > 1) { 
          aQName = s[1]; 
         } 

         aImpl.addAttribute("", 
           atts.getLocalName(i), aQName, 
           atts.getType(i), atts.getValue(i)); 
        } 

       } 

       String[] s = qName.split(":"); 
       if (s.length > 1) { 
        super.startElement("", localName, s[1], aImpl); 
       } else { 
        super.startElement("", localName, qName, aImpl); 
       } 

     } 

     @Override 
     public void endElement(String uri, String localName, 
       String qName) throws SAXException { 

       String[] s = qName.split(":"); 
       if (s.length > 1) { 
       super.endElement("", localName, s[1]); 
       } else { 
        super.endElement("", localName, qName); 
       } 

     } 

     @Override 
     public void startPrefixMapping(String prefix, String uri) { 
     } 

    }; 

    xf.setFeature("http://xml.org/sax/features/namespaces", false); 
    SAXSource src = new SAXSource(xf, file); 

    StringWriter stringWriter = new StringWriter(); 
    TransformerFactory transformerFactory = TransformerFactory 
      .newInstance(); 
    Transformer transformer = transformerFactory.newTransformer(); 
    transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"yes"); 
    transformer.transform(src, new StreamResult(stringWriter)); 

    String xml = stringWriter.toString(); 
    System.out.println(xml); 

} catch (Exception e) { 
    e.printStackTrace(); 
} 
+1

Das ist ein schrecklicher Ansatz - Sie versuchen nicht, Sonderzeichen in der Ausgabe zu entkommen! Im Allgemeinen ist das Serialisieren von Hand fast so schwerwiegend wie das Parsen von Hand. In mancher Hinsicht ist es schlimmer, weil andere Leute mit der ungültigen Ausgabe umgehen müssen, die Sie erstellen. –

+0

@MichaelKay OK Ich verstehe es, ich bin neugierig, wie ich Sonderzeichen entkommen muss, wenn ich es jemals tun muss. Außerdem füge ich einfach alles an, was ich vom Parser bekomme, oder? Was vermisse ich ? – SomeDude

+0

Es ist nicht schwer, es richtig zu machen, obwohl eine Menge Leute es anscheinend nicht richtig machen, aber der beste Ansatz ist die Verwendung einer existierenden Serialisierungsbibliothek. Ein gängiger Ansatz besteht beispielsweise darin, eine Identitätstransformation in ein StreamResult durchzuführen. –

0

In der Regel versucht t o Namespaces zu entfernen, um eine "Transformation" durchzuführen, ist ein Zeichen mangelnder Kenntnisse darüber, wie XML gehandhabt wird. Wenn Sie jedoch im Allgemeinen SAX verwenden und das verarbeitete XML ändern möchten, können Sie einen Filter https://docs.oracle.com/javase/8/docs/api/org/xml/sax/XMLFilter.html implementieren, beginnend mit https://docs.oracle.com/javase/8/docs/api/org/xml/sax/helpers/XMLFilterImpl.html als Basisklasse und Überschreiben der Methoden, die Sie erwarten, und Entfernen von Namespaces.

+0

Ich habe XMLFilterImpl ausprobiert, den Code hinzugefügt, den ich ausprobiert habe – pradeep

+0

Kannst du mir beim Entfernen der Namespace-Attribute helfen? – pradeep

+0

Ich kenne die SAX-API nicht sehr gut, es sieht so aus, als ob du https://docs.oracle.com/javase/ verwenden solltest 8/docs/api/org/xml/sax/ext/Attribute2Impl.html # Attributes2Impl-- um neue Attribute zu erstellen, von denen, die Ihr Handler erhält, wobei Sie natürlich sicherstellen, dass die neuen Attribute nicht den Namespace haben haben. Sie müssen ein bisschen versuchen, aber ich bin sicher, dass Sie es erarbeiten können. –

1

In diesem Code:

super.startElement(uri, localName, data[1], atts); 

Sie übergeben den ursprünglichen NamespaceURI unverändert zu die Ausgabe. Sie müssen es loswerden, verwenden:

super.startElement("", localName, data[1], atts); 
+0

hi, das funktioniert nicht – pradeep

0

Dies ist ein Beispiel, was mit VTD-XML getan werden kann. Lass es mich wissen, wenn es eine Frage gibt.

import com.ximpleware.*; 
import java.io.*; 
public class removeNS { 

    public static void main(String[] args) throws VTDException, IOException{ 
     // TODO Auto-generated method stub 
     VTDGen vg = new VTDGen(); 
     if (!vg.parseFile("d:\\xml\\ns.xml", true)) 
      return; 
     VTDNav vn = vg.getNav(); 
     XMLModifier xm = new XMLModifier(vn); 
     for (int i=0;i<vn.getTokenCount();i++){ 

      int t = vn.getTokenType(i); 
      switch(t){ 

       case VTDGen.TOKEN_STARTING_TAG: 
        stripElementPrefix(i,vn,xm); 
        break; 
       case VTDGen.TOKEN_ATTR_NAME: 
        stripAttrPrefix(i,vn,xm); 
        break; 
       case VTDGen.TOKEN_ATTR_NS: 
        xm.removeAttribute(i); 
       default: 
      } 
     } 
     xm.output("d:\\xml\\nsOut.xml"); 
    } 

    public static void stripAttrPrefix(int i, VTDNav vn, XMLModifier xm) throws VTDException{ 
     //get the offset and length of localname part of starting tag 
     int os1 = vn.getTokenOffset(i); 
     int len = vn.getTokenLength(i); 
     if ((len>>16)!=0){ 
      int temp1 = (0xffff & len) - (len>>16)-1; 
      int temp2 = os1 + (temp1); 
      xm.removeContent(temp1, temp2); 
     } 

     //int offset= 
    } 

    public static void stripElementPrefix(int i, VTDNav vn, XMLModifier xm) throws VTDException, UnsupportedEncodingException{ 
     //int os1 = vn.getTokenOffset(i) 
     int os1 = vn.getTokenOffset(i); 
     int len = vn.getTokenLength(i); 
     if ((len>>16)!=0){ 
      int temp1 = (0xffff & len) - (len>>16)-1; 
      int temp2 = os1 + (len>>16)+1; 
      String s = vn.toRawString(temp2, temp1); 
      System.out.println(s); 
      vn.recoverNode(i); 
      xm.updateElementName(s); 
     } 
    } 

} 
Verwandte Themen