tags:

views:

54

answers:

3

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/"&gt;
<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.

A: 

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 http://stackoverflow.com/questions/2811001/how-to-read-xml-using-xpath-in-java

Robert Diana
+2  A: 

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.

McDowell
@McDowell I get this error "ERROR: 'Namespace for prefix 'soapenv' has not been declared.'" , how can I fix it?
c0mrade
I meant to say SOAP-ENV sorry
c0mrade
@c0mrade - setting `IS_NAMESPACE_AWARE` false on the StAX parser disables namespace awareness. Using the same document and sample code, all prefixed elements are removed. XSLT requires namespace awareness, so if you have other elements with prefixes you'll either need to operate on valid documents or avoid transformers when generating the DOM.
McDowell
@McDowell it wasn't the total solution but it sure got me there, thank you for you time and effort
c0mrade
A: 

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.

Thorbjørn Ravn Andersen
@Thorbjørn Ravn Andersen thank you for your answer can you provide me with some links to get me started
c0mrade