Search code examples
javaxmlsaxparser

how to remove xml namesapce with SAX parser


I need to do xml transformation with SAX parser, for that i need to remove namespace from the xml. Since we are handling with huge xml, i need to use SAX parser.

sample input xml:

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

with the help of SAX parser, i need the below output.

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

Thanks in advance..

The code which i tried,

i tried with XMLFlterImpl,

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

this removes the element name prefix(namespace), but not sure how to remove the namespace attributes


Solution

  • EDIT:

    Ok, with direction from comments from @MichaelKay, here is my updated answer.

    To remove namespace from tags:

    As suggested in his answer, the startElement should have "" in place of uri. What about Ending tag ?: In your question I don't understand why you want ns2 for ending meta tag particularly when you want to remove it for the starting tag. I assume you want it to be removed for ending tag too. So similarly endElement should also have "" in place of uri.

    Filter XMLNS attributes:

    You could create a new AttributesImpl. Then go through the list of attributes and check if the QName starts with xmlns, if not add it to the AttributesImpl and use it in the startElement as :

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

    Also note that as per @MartinHonnen, yes the attributes' uri should also be "" and also the qName should be without prefix as with elements. But if you want to keep the attributes' names as such ( which I don't think you want to ) you can just keep atts.getQName(i) as is.

    Also set Namespaces feature to false like :

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