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);
            }
        }
相关推荐
弹简特8 小时前
【JavaEE19-后端部分】 MyBatis 入门第三篇:使用XML完成增删改查
xml·mybatis
spencer_tseng14 小时前
Tomcat server.xml <Connector> address=“0.0.0.0“
xml·tomcat
常利兵2 天前
Android 字体字重设置:从XML到Kotlin的奇妙之旅
android·xml·kotlin
Predestination王瀞潞2 天前
2.4 编码->W3C XML 1.0标准(W3C Recommendation):XML(Extensible Markup Language)
xml·前端
青槿吖3 天前
【保姆级教程】Spring事务控制通关指南:XML+注解双版本,避坑指南全奉上
xml·java·开发语言·数据库·sql·spring·mybatis
北京聚信万通科技有限公司3 天前
Odette OFTP2 Group1/2/3深度解读:PDX XML能力划分与选型指南
xml·edi·电子数据交换·as2·国产软件·oftp2
小趴蔡ha5 天前
如何将XML格式标注文件转换为YOLO格式进行目标检测训练(附代码)
xml·yolo·目标检测
__Yvan5 天前
解决ConstraintLayout中LinearLayout显示异常问题
android·xml·约束布局
weixin_307779136 天前
构建健壮的XML文档抓取与摘要流水线:Requests + urllib3.Retry + lxml 实践
xml·开发语言·python·算法·性能优化
kgduu6 天前
js之xml处理
xml·前端·javascript