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
相关产品推荐
相关产品推荐

