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);
            }
        }
相关推荐
丑八怪大丑4 天前
XML_Tomcat_HTTP
xml·http·tomcat
largecode5 天前
企业名称能在来电显示吗?号码显示公司名服务打通多终端展示
android·xml·ios·iphone·xcode·webview·phonegap
只可远观7 天前
Android XML命令式和Jetpack Compose声明式UI
android·xml
鹏晨互联7 天前
《深入理解 Compose 中的 matchParentSize 与 fillMaxSize —— 从 XML 到 Compose 的对比解析》
xml
小短腿的代码世界7 天前
Qt SVG渲染管线全解析:从XML解析到像素绘制的完整架构设计与性能优化实战
xml·qt·性能优化
HMS工业网络8 天前
技术干货:EtherCAT设备ESI(XML)文件中的CompleteAccess关键字有什么作用
xml·运维·服务器
鹏晨互联9 天前
【Compose vs XML:边框内外间距的实现对比】
android·xml
鹏晨互联10 天前
Jetpack Compose vs XML:fillMaxSize、fillMaxHeight、fillMaxWidth 全面对比
android·xml
如果'\'真能转义说11 天前
OOXML 文档格式剖析:哈希、ZIP结构与识别
xml·算法·c#·哈希算法