dom4j解析含有命名空间的XML

XML 复制代码
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <s4000CfmTransferResponse
            xmlns="http://service.ccbs.test.com/">
            <return>
                <ROOT>
                    <OUT_DATA>
                        <USER_INFO>
                            <PHONE_NO>1</PHONE_NO>
                            <STAND_ADDRESS>2</STAND_ADDRESS>
                            <ITEL_ACCOUNT>3</ITEL_ACCOUNT>
                            <SVC_ID>4</SVC_ID>
                            <SVC_NAME>5</SVC_NAME>
                            <PROD_ID>6</PROD_ID>
                            <IPTV_ACCOUNT>7</IPTV_ACCOUNT>
                        </USER_INFO>
                        <USER_INFO>
                            <PHONE_NO>8</PHONE_NO>
                            <STAND_ADDRESS>9</STAND_ADDRESS>
                            <ITEL_ACCOUNT>10</ITEL_ACCOUNT>
                            <SVC_ID>11</SVC_ID>
                            <SVC_NAME>12</SVC_NAME>
                            <PROD_ID>13</PROD_ID>
                            <IPTV_ACCOUNT>14</IPTV_ACCOUNT>
                        </USER_INFO>
                        <USER_INFO>
                            <PHONE_NO>15</PHONE_NO>
                            <STAND_ADDRESS>16</STAND_ADDRESS>
                            <ITEL_ACCOUNT>17</ITEL_ACCOUNT>
                            <SVC_ID>18</SVC_ID>
                            <SVC_NAME>19</SVC_NAME>
                            <PROD_ID>20</PROD_ID>
                            <IPTV_ACCOUNT>21</IPTV_ACCOUNT>
                        </USER_INFO>
                    </OUT_DATA>
                    <RETURN_MSG>OK</RETURN_MSG>
                    <PROMPT_MSG/>
                    <RETURN_CODE>0</RETURN_CODE>
                    <USER_MSG>OK</USER_MSG>
                    <DETAIL_MSG>OK</DETAIL_MSG>
                    <RUN_IP>xxx</RUN_IP>
                </ROOT>
            </return>
        </s4000CfmTransferResponse>
    </soap:Body>
</soap:Envelope>

1、未处理名称空间返回为空

java 复制代码
        //解析xml
        Document document = DocumentHelper.parseText(xml);
        Element root = document.getRootElement();

        //0代表成功
        String retCode = root.selectSingleNode("//ROOT/RETURN_CODE").getText().trim();
        List<Object> list = new ArrayList<>();
        if ("0".equals(retCode)) {
            List<Node> nodes = root.selectNodes("//ROOT/OUT_DATA/USER_INFO");
            for (Node node : nodes) {
                String PHONE_NO = node.selectSingleNode("PHONE_NO").getText();
                String STAND_ADDRESS = node.selectSingleNode("STAND_ADDRESS").getText();
                HashMap<String, Object> map = new HashMap<>();
                map.put("PHONE_NO", PHONE_NO);
                map.put("STAND_ADDRESS", STAND_ADDRESS);
                list.add(map);
            }
        }

2、处理xml的名称空间,已经能正常获取值了。这一步是测试,就是没有标签没有前缀,但是需要得到没有前缀默认的名称空间

java 复制代码
        //解析xml
        Document document = DocumentHelper.parseText(xml);
        Element root = document.getRootElement();

        // 添加命名空间,作用域在整个文档
        Map<String, String> xmlMap = new HashMap<>();
        // 因为有2个命名空间属性,所以添加2个
        xmlMap.put("soap", "http://schemas.xmlsoap.org/soap/envelope/");
        xmlMap.put("xmlns", "http://service.ccbs.test.com/");


        XPath xpath = document.createXPath("//soap:Envelope/soap:Body");
        xpath.setNamespaceURIs(xmlMap);
        // 获取第二层xml的命名空间,因为s4000CfmTransferResponse没有名称空间,我需要看默认s4000CfmTransferResponse的名称空间
        String secendUrl = ((Element) xpath.selectSingleNode(document)).element("s4000CfmTransferResponse").getNamespaceURI();
        System.out.println("默认的名称空间:" + secendUrl);

        xpath = document.createXPath("//soap:Envelope/soap:Body/xmlns:s4000CfmTransferResponse");
        xpath.setNamespaceURIs(xmlMap);
        Node node2 = xpath.selectSingleNode(document);


        xpath = document.createXPath("//xmlns:ROOT/xmlns:OUT_DATA/xmlns:USER_INFO");
        xpath.setNamespaceURIs(xmlMap);
        List<Node> node3 = xpath.selectNodes(document);

如果不知道标签的名称空间是什么,可以用下面的方法打印xml所有标签的名称空间

java 复制代码
    /**
     * 打印名称空间
     */
    public static void outNamespace(String xml) throws DocumentException {
        // xml必须有一个根节点
        xml = "<root>" + xml + "</root>";
        Document document = DocumentHelper.parseText(xml);
        Element root = document.getRootElement(); //根节点
        outNamespace(root);
    }

    /**
     * 打印名称空间
     */
    private static void outNamespace(Element element) {
        List<Element> list = element.elements(); //获取所有子节点
        for (Element iter : list) { //遍历所有子节点
            if (iter.elements().size() > 0) { //子节点还有子节点
                outNamespace(iter); //递归调用
                String name = iter.getName();//标签名称
                String namespaceURI = iter.getNamespaceURI();//名称空间
                System.out.println(name + "=" + namespaceURI);
            } else { //子节点无子节点
                String name = iter.getName();//标签名称
                String namespaceURI = iter.getNamespaceURI();//名称空间
                System.out.println(name + "=" + namespaceURI);
            }
        }
    }

3、最后正常的处理方式如下:

XML 复制代码
        //解析xml
        Document document = DocumentHelper.parseText(xml);
        Element root = document.getRootElement();
        // 添加命名空间
        Map<String, String> xmlMap = new HashMap<>();
        // 因为有2个命名空间属性,所以添加2个
        xmlMap.put("soap", "http://schemas.xmlsoap.org/soap/envelope/");
        xmlMap.put("xmlns", "http://service.ccbs.test.com/");
        //XPath解析,带名称空间
        XPath xpath = document.createXPath("//xmlns:ROOT/xmlns:RETURN_CODE");
        xpath.setNamespaceURIs(xmlMap);

        //0代表成功
        String retCode = xpath.selectSingleNode(document).getText().trim();
        List<Object> list = new ArrayList<>();
        if ("0".equals(retCode)) {
            xpath = document.createXPath("//xmlns:ROOT/xmlns:OUT_DATA/xmlns:USER_INFO");
            xpath.setNamespaceURIs(xmlMap);
            List<Node> nodes = xpath.selectNodes(document);
            for (Node node : nodes) {
                String PHONE_NO = ((Element) node).element("PHONE_NO").getText();
                String STAND_ADDRESS = ((Element) node).element("STAND_ADDRESS").getText();
                HashMap<String, Object> map = new HashMap<>();
                map.put("PHONE_NO", PHONE_NO);
                map.put("STAND_ADDRESS", STAND_ADDRESS);
                list.add(map);
            }
        }
相关推荐
fatiaozhang95274 小时前
中国移动中兴云电脑W132D-RK3528-2+32G-刷机固件包(非原机制作)
android·xml·电脑·电视盒子·刷机固件·机顶盒刷机
Ray Song5 小时前
【FastDDS】XML profiles
xml·中间件·自动驾驶·dds·fastdds
l1t6 小时前
我改写的二分法XML转CSV文件程序速度追上了张泽鹏先生的
xml·c语言·人工智能·算法·expat
困到晕阙18 小时前
[NCTF2019]Fake XML cookbook
xml·xxe
ruleslol20 小时前
五分钟XML速成
xml
令狐少侠20112 天前
maven settings.xml文件的各个模块、含义以及它们之间的联系
xml·maven
l1t2 天前
张泽鹏先生手搓的纯ANSI处理UTF-8与美团龙猫调用expat库读取Excel xml对比测试
xml·人工智能·excel·utf8·expat
charlie1145141912 天前
Android开发——初步了解AndroidManifest.xml
android·xml·开发语言·学习·安卓·安全架构
热烈勒温2 天前
Mybatis入门、操作数据、配置xml映射、数据封装
xml·mybatis
微笑伴你而行3 天前
目标检测如何将同时有方形框和旋转框的json/xml标注转为txt格式
xml·目标检测·json