RestAPI新手求助:Java解析Rest XML响应并提取特定实体
在Java中解析Rest XML响应提取多个值的方案
嘿,作为经常和Java XML解析打交道的开发者,我来帮你搞定这个问题!你需要从Rest API返回的XML响应里提取所有<objectId>标签的内容(比如<objectId>virtualwire-3560</objectId>这类),而且可能有多个,对吧?下面给你几种实用的方案,按需选择就行:
方法一:使用DOM解析
DOM会把整个XML加载到内存中,适合小到中等规模的XML响应,操作起来直观易懂,很适合你的场景。
实现步骤&代码示例:
import org.w3c.dom.Document; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import java.io.StringReader; public class XmlObjectIdExtractor { public static void main(String[] args) { // 替换成你实际从Rest API获取的XML响应字符串 String xmlResponse = "<virtualWires><dataPage><pagingInfo><pageSize>10</pageSize><startIndex>0</startIndex><totalCount>4660</totalCount><sortOrderAscending>true</sortOrderAscending></pagingInfo><virtualWires><objectId>virtualwire-3560</objectId><objectId>virtualwire-3561</objectId></virtualWires></dataPage></virtualWires>"; try { // 初始化DOM解析器 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new StringReader(xmlResponse)); // 使用XPath查询所有<objectId>节点 XPath xpath = XPathFactory.newInstance().newXPath(); NodeList objectIdNodes = (NodeList) xpath.evaluate("//objectId", doc, javax.xml.xpath.XPathConstants.NODESET); // 遍历节点提取内容 for (int i = 0; i < objectIdNodes.getLength(); i++) { String objectId = objectIdNodes.item(i).getTextContent().trim(); System.out.println("提取到的ObjectId: " + objectId); } } catch (Exception e) { e.printStackTrace(); } } }
方法二:使用SAX解析
如果你的XML响应特别大(比如包含上万条数据),DOM会占用太多内存,这时候SAX解析是更好的选择——它是流式解析,逐行读取XML,遇到目标标签时才提取内容,内存占用极低。
实现步骤&代码示例:
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.StringReader; public class SaxObjectIdExtractor { public static void main(String[] args) { String xmlResponse = "<virtualWires><dataPage><pagingInfo><pageSize>10</pageSize><startIndex>0</startIndex><totalCount>4660</totalCount><sortOrderAscending>true</sortOrderAscending></pagingInfo><virtualWires><objectId>virtualwire-3560</objectId><objectId>virtualwire-3561</objectId></virtualWires></dataPage></virtualWires>"; try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); // 自定义SAX处理器,监听<objectId>标签 DefaultHandler handler = new DefaultHandler() { private boolean isObjectIdTag = false; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 遇到<objectId>标签时标记状态 if (qName.equalsIgnoreCase("objectId")) { isObjectIdTag = true; } } @Override public void characters(char ch[], int start, int length) throws SAXException { // 如果当前是<objectId>标签内的内容,提取并输出 if (isObjectIdTag) { String objectId = new String(ch, start, length).trim(); System.out.println("提取到的ObjectId: " + objectId); isObjectIdTag = false; // 重置状态,避免重复读取 } } }; saxParser.parse(new StringReader(xmlResponse), handler); } catch (Exception e) { e.printStackTrace(); } } }
方法三:使用JAXB(XML对象绑定)
如果可以提前定义对应XML结构的Java实体类,JAXB会让解析变得异常优雅——它自动把XML映射成Java对象,你直接调用getter方法就能拿到数据,代码可读性极高。
第一步:定义对应XML结构的Java实体类
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.util.List; @XmlRootElement(name = "virtualWires") public class VirtualWiresResponse { private DataPage dataPage; @XmlElement(name = "dataPage") public DataPage getDataPage() { return dataPage; } public void setDataPage(DataPage dataPage) { this.dataPage = dataPage; } // 内部类对应dataPage节点 public static class DataPage { private PagingInfo pagingInfo; private List<VirtualWire> virtualWires; @XmlElement(name = "pagingInfo") public PagingInfo getPagingInfo() { return pagingInfo; } public void setPagingInfo(PagingInfo pagingInfo) { this.pagingInfo = pagingInfo; } @XmlElement(name = "virtualWires") public List<VirtualWire> getVirtualWires() { return virtualWires; } public void setVirtualWires(List<VirtualWire> virtualWires) { this.virtualWires = virtualWires; } } // 内部类对应pagingInfo节点 public static class PagingInfo { private int pageSize; private int startIndex; private int totalCount; private boolean sortOrderAscending; @XmlElement(name = "pageSize") public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } @XmlElement(name = "startIndex") public int getStartIndex() { return startIndex; } public void setStartIndex(int startIndex) { this.startIndex = startIndex; } @XmlElement(name = "totalCount") public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } @XmlElement(name = "sortOrderAscending") public boolean isSortOrderAscending() { return sortOrderAscending; } public void setSortOrderAscending(boolean sortOrderAscending) { this.sortOrderAscending = sortOrderAscending; } } // 内部类对应单个virtualWire节点 public static class VirtualWire { private String objectId; @XmlElement(name = "objectId") public String getObjectId() { return objectId; } public void setObjectId(String objectId) { this.objectId = objectId; } } }
第二步:使用JAXB解析XML并提取数据
import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import java.io.StringReader; public class JaxbObjectIdExtractor { public static void main(String[] args) { String xmlResponse = "<virtualWires><dataPage><pagingInfo><pageSize>10</pageSize><startIndex>0</startIndex><totalCount>4660</totalCount><sortOrderAscending>true</sortOrderAscending></pagingInfo><virtualWires><objectId>virtualwire-3560</objectId><objectId>virtualwire-3561</objectId></virtualWires></dataPage></virtualWires>"; try { // 初始化JAXB上下文 JAXBContext jaxbContext = JAXBContext.newInstance(VirtualWiresResponse.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); // 将XML字符串解析为Java对象 VirtualWiresResponse response = (VirtualWiresResponse) unmarshaller.unmarshal(new StringReader(xmlResponse)); // 遍历提取所有objectId for (VirtualWiresResponse.VirtualWire wire : response.getDataPage().getVirtualWires()) { System.out.println("提取到的ObjectId: " + wire.getObjectId()); } } catch (Exception e) { e.printStackTrace(); } } }
方案选择建议
- 如果XML响应数据量小,优先选DOM或者JAXB,代码简单易维护;
- 如果是超大XML响应,选SAX,避免内存溢出问题;
- 如果后续需要频繁操作XML中的其他数据,JAXB是最优雅的选择,因为它把XML转换成了强类型的Java对象。
内容的提问来源于stack exchange,提问作者Suneel Yadava
相关产品推荐
相关产品推荐

