xpath解析xml

今天做了个调WebService的功能,记录一下。

先说明下什么是WebService:

  • (http + xml) = web Service
  • XML:扩展性标记语言
    – xmlns=“http://itcast.cn” 使用默认命名空间。
    – xmlns:itcast=“http://itcast.cn”使用指定名称的命名空间。
  • SOAP:简单对象访问协议,用于网上传输数据。 SOAP = 在HTTP的基础上+XML数据。组成:
    – Envelope – 必须的部分。以XML的根元素出现
    – Headers – 可选的
    – Body – 必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。
  • WSDL:web服务描述语言(说明书)
    – 通过xml格式说明服务的地址
    – 通过xml格式说明服务如何调用

我实现的WebService:

请求接口:http://iofweb.xxx.com.cn/TradeService
请求报文:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:int="http://interfaces.service.xxx.com">
   <soapenv:Header/>
   <soapenv:Body>
      <int:getTradeData/>
   </soapenv:Body>
</soapenv:Envelope>

返回报文:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Body>
      <ns1:getTradeDataResponse xmlns:ns1="http://interfaces.service.xxx.com">
         <ns1:out>
            <fundCode xmlns="http://VO.xxx.com">000930</fundCode>
            <purchaseAmount xmlns="http://VO.xxx.com">0.00</purchaseAmount>
            <purchaseNum xmlns="http://VO.xxx.com">0</purchaseNum>
            <redeemAmount xmlns="http://VO.xxx.com">76853.20</redeemAmount>
            <redeemNum xmlns="http://VO.xxx.com">1638</redeemNum>
            <retCode xmlns="http://VO.xxx.com">0000</retCode>
            <retMsg xmlns="http://VO.xxx.com">success</retMsg>
            <transactionDate xmlns="http://VO.xxx.com">20191022</transactionDate>
         </ns1:out>
      </ns1:getTradeDataResponse>
   </soap:Body>
</soap:Envelope>

请求并解析返回报文:

/**
     * 请求WebService,并解析返回报文
     *
     * @param url:接口路径  (http://iofweb.xxx.com.cn/TradeService)
     * @param xpath :xml解析节点路径 (/soap:Envelope/soap:Body/ns1:getTradeDataResponse/ns1:out)
     * @param packet: 请求报文(上面的)
     * */
    public static List<Map<String,String>> getWebServiceRecord(String url,String xpath){
       ResponseEntity<String> response = null; 
        HttpEntity<String> request = new HttpEntity<>(packet);
        try{
            URI uri = URI.create(url);
            response = HttpInvoker.getInstance().postForEntity(uri,request,String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
               String responseBody = response.getBody();
                if (StringUtils.contains(responseBody,ApiConst.WS_BIZ_SUCCESS_KEY)) {   //请求成功的标识(自定义)
                    List<Map<String,String>> records = xmlToMap(xpath,responseBody);
                    return records;
                } else {
                    throw Tools.newException("获取WebService数据失败:",responseBody);
                }
            } else {
                throw Tools.newException("获取WebService数据失败:状态码[", response.getStatusCodeValue(), "]");
            }
        }catch (IllegalArgumentException e){
            throw Tools.newException("调用WebService参数格式非法:"+Tools.getRootCauseMessage(e));
        } catch (Exception e) {
            throw Tools.newException("调用WebService异常:"+e);
        }
    }
    public static List<Map<String,String>> xmlToMap(String xpath,String responseBody) throws DocumentException {
        List<Map<String,String>> records = Lists.newArrayList();
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new StringReader(responseBody));
        XPath xPath = document.createXPath(xpath);
        Map<String, String> names = new HashMap<String, String>();
        names.put("soap",  "http://schemas.xmlsoap.org/soap/envelope/");
        names.put(“ns1”,“http://interfaces.service.xxx.com”);
        xPath.setNamespaceURIs(names);
        List<Element> nodes = xPath.selectNodes(document);
        if (CollectionUtils.isEmpty(nodes)) {
            records = Collections.EMPTY_LIST;
        } else {
            for (Element node : nodes) {
                Map<String,String> nodeMap = new HashMap<>();
                List<Element> elements = node.elements();
                elements.forEach(element -> nodeMap.put(element.getName(),element.getTextTrim()));
                records.add(nodeMap);
            }
        }
        return records;
    }

这里请求用的是http请求,post方式。
调用的是接口的getTradeData方法。
用了xpath解析返回的报文:xpath的值是/soap:Envelope/soap:Body/ns1:getTradeDataResponse/ns1:out,从报文根节点开始一直到最内层。将解析后的内容以map形式保存在list中即可。
特别注意的是,在返回的报文中,ns1节点有自定义命名空间。由于WebService默认只将根节点的命名空间加载进去,程序执行时无法识别ns1的命名空间,所以需要手动添加进去,同时不能覆盖根节点soap的命名空间。即这两句代码:

names.put(“soap”, “http://schemas.xmlsoap.org/soap/envelope/”);
names.put(“ns1”,“http://interfaces.service.xxx.com”);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值