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);
            }
        }
相关推荐
小刘同学++1 小时前
Qt 处理 XML 数据
xml·qt
曹牧11 小时前
Java:XML被自动转义
xml·java·开发语言
FL1717131412 小时前
Mujoco & robosuite 机器人模型
xml·java·机器人
程序员的世界你不懂14 小时前
关于 xpath 查找 XML 元素的一点总结
xml
limengshi1383921 天前
使用Python将YOLO的XML标注文件转换为TXT文件格式
xml·python·yolo
亮学长2 天前
介绍XML
xml
攒了一袋星辰2 天前
Spring如何通过XML注册Bean
xml·java·spring
yuren_xia2 天前
示例:spring xml+注解混合配置
xml·java·spring
百锦再3 天前
SQLiteDatabase 增删改查(CRUD)详细操作
android·xml·java·ide·android studio·安卓
Code哈哈笑3 天前
【Spring Boot基础】MyBatis的基础操作:增删查改、列名和属性名匹配 -- XML实现
xml·java·spring boot·后端·spring·mybatis