ant
ant

Reputation: 22948

Is it possible to ignore/skip nodes while parsing xml in Java

I'm trying to remove SOAP and ns2 nodes from this XML :

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"       SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns2:createCustomer>
    <Customer>
        <CustomerId/>
        <names>
            <firstName>fName</firstName>
            <lastName>lName</lastName>
            <middleName>nName</middleName>
            <nickName/>
            </names>
        <addressList>
            <address>
                <streetInfo>
                    <houseNumber>22</houseNumber>
                    <baseName>Street base name</baseName>
                    <district>kewl district</district>
                    </streetInfo>
                <zipcode>22231</zipcode>
                <state>xxx</state>
                <country>xxxz</country>
                <primary>true</primary>
                </address>
            </addressList>
        <SSN>561381</SSN>
        <phone>
            <homePhone>123123123</homePhone>
            <officePhone/>
            <homePhone>21319414</homePhone>
            </phone>
        <preferred>true</preferred>
        </Customer>
        </ns2:createCustomer>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Is this possible before this :

Document doc = parser.parse(xmlFile); 
NodeList startlist = doc.getChildNodes();

I tried to read this as String then writing it back to the XML file like this :

private void preParsing(String fileName,String ...tags) {

        try {

            BufferedReader br = new BufferedReader(new FileReader(new File(fileName)));
            StringBuilder sb = new StringBuilder();
            String line;

            while ((line = br.readLine()) != null) {
                for (String string : tags) {
                    if(!line.contains(string)){
                        sb.append(line);
                        sb.append("\n");
                    }
                }
            }           

            System.out.println(sb.toString());

            br.close();

        } catch (IOException e) {
            System.err.println("Error occured: " + e.getMessage());
        }

    }

It worked if I ignore only one tag like :

preParsing("src/main/resources/test.xml", "SOAP");

But it didn't work when I pass more than one tag argument to ignore/remove from file. I'm sure there is more elegant way of doing this I just can't think of any.

Upvotes: 1

Views: 5787

Answers (3)

A common approach to manipulate XML documents, is to use XSLT. This e.g. allow you to write filters that can remove any tag in a specific namespace, and much more.

The XSLT language is quite different from Java, but there is a XSLT processor (check the Templates and Transformer classes) in Java since 1.4, so it is well supported.

Upvotes: 0

McDowell
McDowell

Reputation: 108879

You could use a StAX filter:

class MyFilter implements EventFilter {
  private final List<String> filtered = Arrays.asList("SOAP-ENV:Envelope",
      "SOAP-ENV:Body", "ns2:createCustomer");

  @Override
  public boolean accept(XMLEvent event) {
    if (event.isStartElement())
      for (String elementName : filtered)
        if (event.asStartElement().getName().getLocalPart().equals(
            elementName))
          return false;
    if (event.isEndElement())
      for (String elementName : filtered)
        if (event.asEndElement().getName().getLocalPart().equals(
            elementName))
          return false;
    return true;
  }
}

Usage:

DOMResult result = new DOMResult();
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
xmlInputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
XMLEventReader reader = xmlInputFactory
    .createXMLEventReader(new StreamSource(new File("soap.xml")));
reader = xmlInputFactory.createFilteredReader(reader, new MyFilter());
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
transformer.transform(new StAXSource(reader), result);
Document document = (Document) result.getNode();

FYI: SOAP-ENV and ns2 are not elements; they are namespace prefixes. The document is malformed - there is missing namespace declarations & the above code is not what I would write for a valid namespaced document.

Upvotes: 4

Robert Diana
Robert Diana

Reputation: 860

Your best bet is to load the document normally, and use XPath to get at the parts that you want.

There is some good info at How to read XML using XPath in Java

Upvotes: 0

Related Questions