您可以通过多种方式从 XML 中提取数据并在 Java 中使用它。您选择哪一种取决于您希望如何使用数据。
一些场景是:
- 您可能想要操作节点、排序、删除和添加其他节点以及转换 XML。
- 您可能只想阅读(并可能更改)元素和属性中包含的文本。
- 您可能有一个非常大的文件,而您只想找到一些特定数据而忽略文件的其余部分。
对于场景 #3,最好的选择是一些内存效率高的基于流的解析器,例如 SAX 或带有 StAX 的 XML 阅读器> API。
如果您主要阅读(而不是写作),您也可以将其用于场景 #2,但基于 DOM 的 API 可能更易于使用。您可以使用标准的 DOM org.w3c.dom API 或更类似于 Java 的 API,例如 JDOM 或 DOM4J。如果您希望将 XML 文件与 Java 对象同步,您可能还希望使用完整的 Java-XML 映射 框架,例如 JAXB。
DOM API 也适用于 场景 #1,但在许多情况下,使用 XSLT 可能更简单(通过 javax.xml.transform TrAX强> Java 中的 API)。如果你使用 DOM,你也可以使用 XPath 来选择节点。
我将向您展示如何使用标准 DOM API (org.w3c.dom) 和 XPath (javax.xml.xpath) 提取文件的各个节点的示例。
1.设置
初始化解析器:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
将文件解析为文档对象模型:
Document source = builder.parse(new File("src/main/resources/addresses.xml"));
2。使用 J2SE DOM 选择节点
你使用getDocumentElement()获取根元素:
Element addresses = source.getDocumentElement();
从那里您可以使用getChildNodes() 获取子节点,但这将返回所有 子节点,其中包括文本节点(元素之间的空白)。 addresses.getChildNodes().item(0) 返回<addresses> 标记之后和<address> 标记之前的空格。要获得该元素,您必须选择第二项。更简单的方法是使用getElementsByTagName,它返回一个节点集并获取第一项:
Element addresses_address = (Element)addresses.getElementsByTagName("address").item(0);
许多 DOM 方法返回 org.w3c.dom.Node 对象,您必须对其进行强制转换。有时它们可能不是 Element 对象,因此您必须检查。节点集不会自动转换为数组。它们是org.w3c.dom.NodeList,因此您必须使用.item(0) 而不是[0](如果您使用其他DOM API,例如JDOM 或DOM4J,它看起来会更直观)。
您可以使用addresses.getElementsByTagName 来获取您需要的所有元素,但您必须处理两个<name> 元素的上下文。所以更好的方法是在适当的上下文中调用它:
Element addresses_address = (Element)addresses.getElementsByTagName("address").item(0);
Element addresses_address_name = (Element)addresses_address.getElementsByTagName("name").item(0);
Element addresses_address_street = (Element)addresses_address.getElementsByTagName("street").item(0);
Element addresses_person = (Element)addresses.getElementsByTagName("person").item(0);
Element addresses_person_name = (Element)addresses_person.getElementsByTagName("name").item(0);
Element addresses_person_age = (Element)addresses_person.getElementsByTagName("age").item(0);
这将为您的文件提供所有Element 节点(或您所称的分支)。如果您想要文本节点(作为实际的 Node 对象),您需要将其作为第一个子节点:
Node textNode = addresses2_address_street.getFirstChild();
如果你想要String 的内容,你可以使用:
String street = addresses2_address_street.getTextContent();
3.使用 XPath 选择节点
另一种选择节点的方法是使用 XPath。您将需要 DOM 源,还需要初始化 XPath 处理器:
XPath xPath = XPathFactory.newInstance().newXPath();
你可以像这样提取根节点:
Element addresses = (Element)xPath.evaluate("/addresses", source, XPathConstants.NODE);
所有其他节点都使用类似路径的语法:
Element addresses_address = (Element)xPath.evaluate("/addresses/address", source, XPathConstants.NODE);
Element addresses_address_name = (Element)xPath.evaluate("/addresses/address/name", source, XPathConstants.NODE);
Element addresses_address_street = (Element)xPath.evaluate("/addresses/address/street", source, XPathConstants.NODE);
您也可以使用相对路径,选择不同的元素作为根:
Element addresses_person = (Element)xPath.evaluate("person", addresses, XPathConstants.NODE);
Element addresses_person_name = (Element)xPath.evaluate("person/name", addresses, XPathConstants.NODE);
Element addresses_person_age = (Element)xPath.evaluate("age", addresses_person, XPathConstants.NODE);
你可以像以前一样获取文本内容,因为你有Element对象:
String addressName = addresses_address_name.getTextContent();
但是你也可以直接使用上面相同的方法而不用最后一个参数(默认为字符串)。这里我使用了不同的相对和绝对 XPath 表达式:
String addressName = xPath.evaluate("name", addresses_address);
String addressStreet = xPath.evaluate("address/street", addresses);
String personName = xPath.evaluate("name", addresses_person);
String personAge = xPath.evaluate("/addresses/person/age", source);