You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+Java11:如何将SOAP响应XML转为HotelStay对象?

解决SOAP响应解析问题(获取HotelStay对象列表)

1. 澄清Document对象“为空”的误解

你看到的[#document: null]只是Document对象默认toString()的输出格式,并非实际为空。可以通过打印根节点名称验证解析结果:

System.out.println(doc.getDocumentElement().getNodeName());

正常会输出soap:Envelope,说明Document已正确解析。

2. 修复XML解析的命名空间支持问题

你的SOAP响应包含OTA命名空间(http://www.opentravel.org/OTA/2003/05),默认DocumentBuilderFactory未开启命名空间支持,会导致后续元素查询失败。修改getDocument方法:

public static Document getDocument(final String soapMessage) throws ParserConfigurationException, IOException, SAXException {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    // 开启命名空间支持
    dbf.setNamespaceAware(true);
    DocumentBuilder db = dbf.newDocumentBuilder();
    InputSource is = new InputSource(new StringReader(soapMessage));
    return db.parse(is);
}

3. 获取HotelStay对象列表的两种常用方法

方式一:DOM API直接操作节点

public static List<Element> getHotelStays(Document doc) {
    List<Element> hotelStayList = new ArrayList<>();
    String otaNamespace = "http://www.opentravel.org/OTA/2003/05";
    
    // 定位OTA_HotelAvailRS节点
    Element otaResponse = (Element) doc.getElementsByTagNameNS(otaNamespace, "OTA_HotelAvailRS").item(0);
    if (otaResponse == null) return hotelStayList;
    
    // 定位HotelStays节点
    Element hotelStays = (Element) otaResponse.getElementsByTagNameNS(otaNamespace, "HotelStays").item(0);
    if (hotelStays == null) return hotelStayList;
    
    // 提取所有HotelStay子节点
    NodeList hotelStayNodes = hotelStays.getElementsByTagNameNS(otaNamespace, "HotelStay");
    for (int i = 0; i < hotelStayNodes.getLength(); i++) {
        hotelStayList.add((Element) hotelStayNodes.item(i));
    }
    return hotelStayList;
}

方式二:XPath查询(更简洁)

public static List<Element> getHotelStaysWithXPath(Document doc) throws XPathExpressionException {
    List<Element> hotelStayList = new ArrayList<>();
    XPath xpath = XPathFactory.newInstance().newXPath();
    
    // 设置命名空间映射
    xpath.setNamespaceContext(new NamespaceContext() {
        @Override
        public String getNamespaceURI(String prefix) {
            if ("ota".equals(prefix)) {
                return "http://www.opentravel.org/OTA/2003/05";
            }
            return XMLConstants.NULL_NS_URI;
        }

        @Override
        public String getPrefix(String namespaceURI) { return null; }
        @Override
        public Iterator<String> getPrefixes(String namespaceURI) { return null; }
    });
    
    // 执行XPath查询
    NodeList hotelStayNodes = (NodeList) xpath.evaluate(
        "//ota:OTA_HotelAvailRS/ota:HotelStays/ota:HotelStay", 
        doc, 
        XPathConstants.NODESET
    );
    for (int i = 0; i < hotelStayNodes.getLength(); i++) {
        hotelStayList.add((Element) hotelStayNodes.item(i));
    }
    return hotelStayList;
}

4. 提取HotelStay的属性与子元素信息

拿到HotelStay元素后,可提取如RoomStayRPH属性、酒店名称等信息:

List<Element> hotelStays = getHotelStays(doc);
for (Element hotelStay : hotelStays) {
    // 提取RoomStayRPH属性
    String roomStayRPH = hotelStay.getAttribute("RoomStayRPH");
    System.out.println("RoomStayRPH: " + roomStayRPH);
    
    // 提取BasicPropertyInfo子元素信息
    Element basicInfo = (Element) hotelStay.getElementsByTagNameNS(
        "http://www.opentravel.org/OTA/2003/05", 
        "BasicPropertyInfo"
    ).item(0);
    if (basicInfo != null) {
        String hotelName = basicInfo.getAttribute("HotelName");
        String hotelCode = basicInfo.getAttribute("HotelCode");
        System.out.println("酒店名称: " + hotelName + ", 酒店编码: " + hotelCode);
    }
}

内容的提问来源于stack exchange,提问作者Richard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 23:40:34