如果不同的enteries缺少少量属性,如何将xml解析为哈希映射

时间:2016-06-07 12:36:02

标签: java xml

下面是我要转换为哈希映射的xml:

<dsml>
    <entries>
        <entry dn="uid=7686,c=in,ou=pages,o=example.com">
            <att name="uid">
                <value>7568766</value>
            </att>
            <att name="email">
                <value>new@gmail.com</value>
            </att>
            <att name="callname">
                <value>John</value>
            </att>
        </entry>
        <entry dn="uid=7689,c=in,ou=pages,o=example.com">
            <att name="uid">
                <value>7678766</value>
            </att>
            <att name="callname">
                <value>Mike</value>
            </att>
        </entry>
        <entry dn="uid=7690,c=in,ou=pages,o=example.com">
            <att name="uid">
                <value>75858766</value>
            </att>
            <att name="email">
                <value>old@gmail.com</value>
            </att>
            <att name="callname">
                <value>rahul</value>
            </att>
        </entry>
    </entries>
</dsml>

正如您所看到的那样,其中一个条目不包含电子邮件属性,而这正是产生问题的原因。下面是我用来将其转换为hashmap的代码:

javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath();
String expr = "//dsml/entries/entry/att[@name = 'callname']/value";
NodeList nl = (NodeList) xPath.evaluate(expr, doc, XPathConstants.NODESET);

String expr1 = "/dsml/directory-entries/entry/attr[@name = 'email']/value";
NodeList n2 = (NodeList) xPath.evaluate(expr1, doc, XPathConstants.NODESET);


Map<String, String> map = new HashMap<String, String>();
for (int i=0; i<=2;i++){
    map.put(nl.item(i).getTextContent(), n2.item(i).getTextContent());

    System.out.println(nl.item(i).getTextContent());
    System.out.println(n2.item(i).getTextContent());
}

此代码的输出是: 约翰 new@gmail.com 麦克风 old@gmail.com 拉胡尔 exceptionnull

如果某个属性不存在,那么应该跳过它而不是从下一个条目属性中获取值。

2 个答案:

答案 0 :(得分:2)

您的方法不正确,因为它无法检测到您的条目只有email,后跟只有callname的条目的情况,它将被视为相同的条目然后混合了两个甚至没有相关的信息。我建议修改您的XPath,以便仅保留同时包含emailcallname的条目。

我将如何做到这一点:

// Keep only entries that have both email and callname
String expr = "/dsml/entries/entry[att[@name = 'email'] and att[@name = 'callname']]/att[@name = 'email' or @name = 'callname']/value";
NodeList nl = (NodeList) xPath.evaluate(expr, doc, XPathConstants.NODESET);

Map<String, String> map = new HashMap<>();
for (int i=0; i< nl.getLength(); i++){
    Node node = nl.item(i);
    String name, email;
    // Check whether the current value is the value of the email or callname
    if ("callnamen".equals(node.getParentNode().getAttributes().getNamedItem("name").getTextContent())) {
        name = node.getTextContent();
        email = nl.item(++i).getTextContent();
    } else {
        name = nl.item(++i).getTextContent();
        email = node.getTextContent();
    }
    map.put(name, email);
}
System.out.println(map);

<强>输出:

{rahul=old@gmail.com, John=new@gmail.com}

答案 1 :(得分:1)

只需检查任何元素的内容是否为null,并相应地更新哈希映射。例如:

 map.put(nl.item(i).getTextContent(), n2.item(i).getTextContent()==null?"":n2.item(i).getTextContent());

或者只是事先检查以检查空值:

if(nl.item(i).getTextContent()!=null && n2.item(i).getTextContent()!=null){
//Put into map
}