在具有未知属性的Java中解析XML

时间:2017-08-02 10:35:37

标签: java xml

我需要将java中的JSON解析为哈希映射。我尝试了一种方法,给出了它的标签名称和属性。虽然我需要一个通用版本,它将将根元素 t的第一个子元素的所有属性解析为哈希映射。

我试过这段代码

public static void main() {
     Map<String, String> map = new HashMap<String, String>();
     String cfgXml = "<response><result code=\"0\" whatever=\"Whatever\"/></response>";
     try
        {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(new InputSource(new StringReader(cfgXml)));
            doc.getDocumentElement().normalize();
            System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
            NodeList nList = doc.getElementsByTagName("result");
            System.out.println("----------------------------");
            for (int temp = 0; temp < nList.getLength(); temp++)
            {
                Node nNode = nList.item(temp);
                System.out.println("\nCurrent Element :" + nNode.getNodeName());
                if (nNode.getNodeType() == Node.ELEMENT_NODE)
                {
                    Element eElement = (Element) nNode;
                    Config c = new Config();
                    c.code = eElement.getAttribute("code");
                    c.whatever = eElement.getAttribute("whatever");
                    if(!map.containsKey(c.code)){
                        map.put("code", c.code);
                        map.put("whatever", c.whatever);
                    }
                    System.out.println(map);
                }
            }
            for (String name: map.keySet()){
                String key =name.toString();
                String value = map.get(name).toString();  
                /*** Key value will be output here **/
                System.out.println(key + "->" + value);  
            } 
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

public static class Config
{
    @Override
    public String toString()
    {
        return "Result [code=" + code + ", whatever=" + whatever + "]";
    }

    public String code;
    public String whatever;
}

这里我得到了输出,但是在这里我将标记名称设为result,并且还给出了属性。我需要一个通用函数,我不知道标记名称和属性,它在不同的XML字符串中会有所不同!

任何帮助将不胜感激

XML文件可以是:

<response>
        <balance balance=”1000000” overdraft=”0”/>
</response>

OR

<response>
<result code=”0”/>
</response>

它可以改变!!

2 个答案:

答案 0 :(得分:2)

考虑这个XML:

SELECT *
FROM (
    SELECT
        @r AS _id,
        (SELECT @r := parent_id FROM data_customers_map_parents WHERE customer_id = _id) AS _pid,
        @l := @l + 1 AS lvl
    FROM
        (SELECT @r := 1, @l := 0) vars,
        data_customers_map_parents m
    WHERE @r != null) T1
JOIN data_customers_map_parents T2
ON T1._id = T2.customer_id
ORDER BY T1.lvl DESC;

在StAX中它会是这样的(没有异常处理):

<root>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <!-- whatever -->
    </project>
</root>

答案 1 :(得分:0)

以下是使用XPath 3.1Saxon 9.8 HE以及XPath表达式map:merge(/*/*[1]/@*!map:entry(local-name(), data()))直接创建XPath 3.1 map的示例,然后您可以将其检索为Map<XdmAtomicValue, XdmValue>使用Saxon的API,如果需要,将其转换为HashMap<String, String>

    Processor proc = new Processor(false);
    XPathCompiler xpath = proc.newXPathCompiler();
    xpath.declareNamespace("map", "http://www.w3.org/2005/xpath-functions/map");

    DocumentBuilder builder = proc.newDocumentBuilder();

    XdmNode input = builder.build(new File(args.length > 0 ? args[0] : "input1.xml"));

    XPathSelector selector = xpath.compile("map:merge(/*/*[1]/@*!map:entry(local-name(), data()))").load();
    selector.setContextItem(input);

    XdmMap map = (XdmMap)selector.evaluateSingle();

    System.out.println(map);
    System.out.println(map.getClass().getName());

    Map<String, String> hashMap = new HashMap<String, String>();
    for (Entry<XdmAtomicValue, XdmValue> entry : map.entrySet())
    {
        hashMap.put(entry.getKey().getStringValue(), entry.getValue().toString());
    }

    System.out.println(hashMap);

输出,例如

map{"overdraft":"0","balance":"1000000"}
net.sf.saxon.s9api.XdmMap
{balance=1000000, overdraft=0}

作为替代方案,如果你知道你想要一个JSON字符串,你可以像上面那样创建XPath 3.1地图,但也可以在XPath中直接将其序列化为JSON:

        Processor proc = new Processor(false);
        XPathCompiler xpath = proc.newXPathCompiler();
        xpath.declareNamespace("map", "http://www.w3.org/2005/xpath-functions/map");

        DocumentBuilder builder = proc.newDocumentBuilder();

        XdmNode input = builder.build(new File(args.length > 0 ? args[0] : "input1.xml"));

        XPathSelector selector = xpath.compile("serialize(map:merge(/*/*[1]/@*!map:entry(local-name(), data())), map { 'method' : 'json' , 'indent' : true()})").load();
        selector.setContextItem(input);

        String json = selector.evaluateSingle().getStringValue();

        System.out.println(json);

输出,例如

 {
  "overdraft":"0",
  "balance":"1000000"
 }