Reputation: 41
I have a XML data from a SOAP Response like in the following example:
<EMP>
<PERSONAL_DATA>
<EMPLID>AA0001</EMPLID>
<NAME>Adams<NAME>
</PERSONAL_DATA>
<PERSONAL_DATA>
<EMPLID>AA0002<EMPLID>
<NAME>Paul<NAME>
</PERSONAL_DATA>
</EMP>
I want to store information about each employee in a Map(KEY,VALUE) KEY=tagname, VALUE=value
and want to create a LIST<MAP>
for all employees using XPATH in java. How is this done?
I tried the following:
public static List createListMap(String path, SOAPMessage response,Map map) {
List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
try {
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("//" + path + "/*");
Object re =expr.evaluate(response.getSOAPBody(), XPathConstants.NODESET);
NodeList nodes = (NodeList)res;
for (int i = 0; i < nodes.getLength(); i++) {
if (nodes.item(i).getFirstChild() != null &&
nodes.item(i).getFirstChild().getNodeType() == 1) {
Map<String, Object> map1 = new HashMap<String, Object>();
map.put(nodes.item(i).getLocalName(), map1);
createListMap(nodes.item(i).getNodeName(), response,map1);
list.add(map);
}
else {
map.put(nodes.item(i).getLocalName(),nodes.item(i).getTextContent());
}
return list;
}
I called a method like createListMap("EMP",response,map);
(response is a SoapResponse).
The problem is coming when in XPATH //PERSONAL_DATA/*
. In recursion it listed data about both of the employees, but I want to store each employee's data in its own map, then create a LIST of those MAP's... How do I do this?
Upvotes: 2
Views: 7273
Reputation: 60414
The expression //PERSONAL_DATA/*
selects all child elements of every PERSONAL_DATA
element, causing exactly the problem you describe. Instead, select the PERSONAL_DATA
elements themselves and iterate their children.
Example:
public NodeList eval(final Document doc, final String pathStr)
throws XPathExpressionException {
final XPath xpath = XPathFactory.newInstance().newXPath();
final XPathExpression expr = xpath.compile(pathStr);
return (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
}
public List<Map<String, String>> fromNodeList(final NodeList nodes) {
final List<Map<String, String>> out = new ArrayList<Map<String,String>>();
int len = (nodes != null) ? nodes.getLength() : 0;
for (int i = 0; i < len; i++) {
NodeList children = nodes.item(i).getChildNodes();
Map<String, String> childMap = new HashMap<String, String>();
for (int j = 0; j < children.getLength(); j++) {
Node child = children.item(j);
if (child.getNodeType() == Node.ELEMENT_NODE)
childMap.put(child.getNodeName(), child.getTextContent());
}
out.add(childMap);
}
return out;
}
Used like this:
List<Map<String, String>> nodes = fromNodeList(eval(doc, "//PERSONAL_DATA"));
System.out.println(nodes);
Output:
[{NAME=Adams, EMPLID=AA0001}, {NAME=Paul, EMPLID=AA0002}]
If you're actually dealing with a more complicated structure, with additional nested elements (which I suspect you are), then you'll need to iterate those layers separately or model your data using something like JAXB.
Upvotes: 4