Извлечение информации XML в список <Map>с использованием XPath - PullRequest
2 голосов
/ 28 ноября 2011

У меня есть данные XML из ответа SOAP, как в следующем примере:

<EMP>
   <PERSONAL_DATA>
     <EMPLID>AA0001</EMPLID>
     <NAME>Adams<NAME>
   </PERSONAL_DATA>
   <PERSONAL_DATA>
     <EMPLID>AA0002<EMPLID>
     <NAME>Paul<NAME>
    </PERSONAL_DATA>
</EMP>

Я хочу хранить информацию о каждом сотруднике в Map(KEY,VALUE) KEY=tagname, VALUE=value и хочу создать LIST<MAP> для всех сотрудников, использующих XPATH в Java. Как это сделать?

Я попробовал следующее:

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

Я вызвал метод, подобный createListMap("EMP",response,map); (ответ - SoapResponse). Проблема наступает, когда в XPATH //PERSONAL_DATA/*. В рекурсии он перечислил данные об обоих сотрудниках, но я хочу сохранить данные каждого сотрудника на его собственной карте, а затем создать СПИСОК этих MAP ... Как мне это сделать?

1 Ответ

3 голосов
/ 29 ноября 2011

Выражение //PERSONAL_DATA/* выбирает все дочерние элементы каждого элемента PERSONAL_DATA, вызывая именно ту проблему, которую вы описываете. Вместо этого выберите сами элементы PERSONAL_DATA и итерируйте их дочерние элементы.

Пример:

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

Используется так:

List<Map<String, String>> nodes = fromNodeList(eval(doc, "//PERSONAL_DATA"));
System.out.println(nodes);

Выход:

[{NAME=Adams, EMPLID=AA0001}, {NAME=Paul, EMPLID=AA0002}]

Если вы на самом деле имеете дело с более сложной структурой, с дополнительными вложенными элементами (я подозреваю, что вы), то вам нужно будет перебрать эти слои отдельно или смоделировать ваши данные, используя что-то вроде JAXB .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...