Thanks, Arjen, I finally figured it out.
In order to implement both handleExampleRequest() and handleSecondElement() symmetrically, I'm creating the source passed to handleExampleRequest() from the document's child node that is the document element of the document (instead of the document itself).
Therefore, both methods now work with elements of the document, and not the document itself.
I attached my example hoping it might be useful for someone else. The important part is the call to getDocumentElement() in the last line of createSource().
Cheers,
Dan
Code:
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.springframework.xml.xpath.Jaxp13XPathTemplate;
import org.springframework.xml.xpath.NodeMapper;
import org.springframework.xml.xpath.XPathOperations;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
public class Test {
public static final String XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<exampleRequest xmlns=\"http://com.example/schemas/test\">\n"
+ " <firstElement>Hi there!</firstElement>\n"
+ " <secondElement someAttribute=\"firstAttributeValue\">\n"
+ " <thirdElement>Hello again!</thirdElement>\n"
+ " </secondElement>\n"
+ " <secondElement someAttribute=\"secondAttributeValue\">\n"
+ " <thirdElement>And again!</thirdElement>\n"
+ " </secondElement>\n"
+ "</exampleRequest>";
public XPathOperations xpathTemplate;
// set up and run test
public Test() throws Exception {
Properties props = new Properties();
props.setProperty("tns", "http://com.example/schemas/test");
Jaxp13XPathTemplate jaxp13XPathTemplate = new Jaxp13XPathTemplate();
jaxp13XPathTemplate.setNamespaces(props);
xpathTemplate = jaxp13XPathTemplate;
Source exampleRequest = createSource(XML);
handleExampleRequest(exampleRequest);
}
// create a source from the xml string
public Source createSource(String xml) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
return new DOMSource(doc.getDocumentElement());
}
// expects a exampleRequest element, extracts the firstElement element and
// passes the secondElement elements to handleSecondElement()
public void handleExampleRequest(Source exampleRequest) {
System.out.println("\n\nHandling ExampleRequest:\n" + format(exampleRequest));
String firstElement = xpathTemplate.evaluateAsString("tns:firstElement", exampleRequest);
System.out.println("found firstElement: " + firstElement);
xpathTemplate.evaluate("tns:secondElement", exampleRequest, new NodeMapper() {
public Object mapNode(Node node, int num) throws DOMException {
Source secondElement = new DOMSource(node);
handleSecondElement(secondElement);
return null;
}
});
}
// expects a secondElement element and extracts the thirdElement element.
// this is the part that does not work as expected.
public void handleSecondElement(Source secondElement) {
System.out.println("\n\nHandling SecondElement:\n" + format(secondElement));
String thirdElement = xpathTemplate.evaluateAsString("tns:thirdElement", secondElement);
System.out.println("found thirdElement: " + thirdElement);
String someAttribute = xpathTemplate.evaluateAsString("@someAttribute", secondElement);
System.out.println("found someAttribute: " + someAttribute);
}
public static void main(String[] args) throws Exception {
new Test();
}
// used for debugging only
public String format(Source source) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
Result result = new StreamResult(bytes);
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, result);
}
catch (TransformerException e) {
System.out.println(e);
}
return bytes.toString().trim();
}
}