如何使用代码读取和写入XML文件

您想学习如何从Java读取和写入XML文件吗?

XML文件用于多种目的,包括数据存储。在JSON流行之前,XML是表示,存储和传输结构化数据的首选格式。尽管XML的流行程度近年来有所下降,但您可能偶尔会遇到它,因此从代码中学习如何使用它很重要。

Java Standard Edition(SE)包括 Java XML处理API(JAXP),是涵盖XML处理大部分方面的总称。这些对象包括:

  • DOM:文档对象模型包括用于处理XML工件(例如元素,节点,属性等)的类。DOMAPI将完整的XML文档加载到内存中用于处理,因此它不太适合处理大型XML文件。
  • SAX: XML的简单API是用于读取XML的事件驱动算法。这里,XML是通过读取XML时触发事件来处理的。使用此方法的内存要求较低,但是使用API​​的方法比使用DOM的复杂。
  • StAX: XML的Streaming API是最近的新增功能XML API,并提供高性能的XML流过滤,处理和修改。虽然它避免将整个XML文档加载到内存中,但它提供了拉动式架构而不是事件驱动式架构,因此与使用SAX API相比,该应用程序更易于编码和理解。
  • 文章中,我们使用 DOM API 来演示如何从Java读取和写入XML文件。在以后的文章中,我们将介绍另外两个API。

    示例XML文件

    出于本文的目的,我们使用以下示例XML演示了概念。此处:

    <?xml version="1.0"?><catalog> <book id="bk101"> <author>Gambardella, Matthew</author> <title>XML Developer's Guide</title> <genre>Computer</genre> <price>44.95</price> <publish_date>2000-10-01</publish_date> <description>An in-depth look at creating applications with XML.</description> </book> <book id="bk102"> <author>Ralls, Kim</author>...

    读取XML文件

    让我们看看使用DOM API读取XML文件所需的基本步骤。

    第一步是获取 DocumentBuilder 的实例。该构建器用于解析XML文档。对于基本用法,我们这样做:

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();factory.setNamespaceAware(false);factory.setValidating(false);DocumentBuilder builder = factory.newDocumentBuilder();

    我们现在可以从XML根元素开始将整个文档加载到内存中。在我们的示例中,它是 catalog 元素。

    File file = ...; // XML file to readDocument document = builder.parse(file);Element catalog = document.getDocumentElement();

    就这样,伙计们!读取XML的DOM API非常简单。现在,您可以从其根元素 catalog 开始访问整个XML文档。现在让我们看看如何使用它。

    使用DOM API

    现在我们有了XML根 Element ,我们可以使用DOM API提取有趣的信息块。

    获取根元素的所有 book 子元素并对其进行循环。请注意, getChildNodes()返回所有子级,包括文本,注释等。出于我们的目的,我们只需要子级元素,因此我们跳过了其他子级。

    NodeList books = catalog.getChildNodes();for (int i = 0, ii = 0, n = books.getLength() ; i < n ; i++) {  Node child = books.item(i);  if ( child.getNodeType() != Node.ELEMENT_NODE )    continue;  Element book = (Element)child;  // work with the book Element here}

    在给定父元素的情况下,如何查找特定的子元素?以下静态方法返回找到的第一个匹配元素,或者为null。如您所见,该过程涉及获取子节点列表并遍历它们,以选择具有指定名称的元素节点。

    static private Node findFirstNamedElement(Node parent,String tagName){  NodeList children = parent.getChildNodes();  for (int i = 0, in = children.getLength() ; i < in ; i++) {    Node child = children.item(i);    if ( child.getNodeType() != Node.ELEMENT_NODE )      continue;    if ( child.getNodeName().equals(tagName) )      return child;  }  return null;}

    请注意,DOM API将元素内的文本内容视为单独的节点类型为 TEXT_NODE 。此外,文本内容可能会拆分为多个相邻的文本节点。因此,需要以下特殊处理才能获取元素内的文本内容。

    static private String getCharacterData(Node parent){  StringBuilder text = new StringBuilder();  if ( parent == null )    return text.toString();  NodeList children = parent.getChildNodes();  for (int k = 0, kn = children.getLength() ; k < kn ; k++) {    Node child = children.item(k);    if ( child.getNodeType() != Node.TEXT_NODE )      break;    text.append(child.getNodeValue());  }  return text.toString();}

    具有这些便捷功能,让我们现在看一下一些代码,这些代码用于列出示例XML中的某些信息。我们希望显示每本书的详细信息,例如在书籍目录中。

    NodeList books = catalog.getChildNodes();for (int i = 0, ii = 0, n = books.getLength() ; i < n ; i++) {  Node child = books.item(i);  if ( child.getNodeType() != Node.ELEMENT_NODE )    continue;  Element book = (Element)child;  ii++;  String id = book.getAttribute("id");  String author = getCharacterData(findFirstNamedElement(child,"author"));  String title = getCharacterData(findFirstNamedElement(child,"title"));  String genre = getCharacterData(findFirstNamedElement(child,"genre"));  String price = getCharacterData(findFirstNamedElement(child,"price"));  String pubdate = getCharacterData(findFirstNamedElement(child,"pubdate"));  String descr = getCharacterData(findFirstNamedElement(child,"description"));  System.out.printf("%3d. book id = %s\n" +  " author: %s\n" +  " title: %s\n" +  " genre: %s\n" +  " price: %s\n" +  " pubdate: %s\n" +  " descr: %s\n",  ii, id, author, title, genre, price, pubdate, descr);}

    编写XML输出

    Java提供了 XML Tranform API 转换XML数据。我们将此API与 identity transform 一起使用以生成输出。

    作为示例,让我们添加一本新的 book 上面显示的样本目录中的元素。这本书的详细信息(例如 author title 等)可以从外部获取,也许可以从属性文件或数据库中获取。我们使用以下属性文件加载数据。

    id=bk113author=Jane Austentitle=Pride and Prejudicegenre=Romanceprice=6.99publish_date=2010-04-01description="It is a truth universally acknowledged, that a single man in possession of a good fortune must be in want of a wife." So begins Pride and Prejudice, Jane Austen's witty comedy of manners-one of the most popular novels of all time-that features splendidly civilized sparring between the proud Mr. Darcy and the prejudiced Elizabeth Bennet as they play out their spirited courtship in a series of eighteenth-century drawing-room intrigues.

    第一步是使用上述方法解析现有XML文件。该代码也显示在下面。

    File file = ...; // XML file to readDocument document = builder.parse(file);Element catalog = document.getDocumentElement();

    我们使用java随附的 Properties 类从属性文件加载数据。代码非常简单,如下所示。

    String propsFile = ...;Properties props = new Properties();try (FileReader in = new FileReader(propsFile)) {  props.load(in);}

    加载属性后,我们将从属性文件中检索要添加的值。

    String id = props.getProperty("id");String author = props.getProperty("author");String title = props.getProperty("title");String genre = props.getProperty("genre");String price = props.getProperty("price");String publish_date = props.getProperty("publish_date");String descr = props.getProperty("description");

    现在让我们创建一个空的 book 元素。

    Element book = document.createElement("book");book.setAttribute("id", id);

    book 中添加子元素是很简单的。为了方便起见,我们将所需的元素名称收集在 List 中,并将值添加到循环中。

    List<String> elnames =Arrays.asList("author", "title", "genre", "price", "publish_date", "description");for (String elname : elnames) {  Element el = document.createElement(elname);  Text text = document.createTextNode(props.getProperty(elname));  el.appendChild(text);  book.appendChild(el);}catalog.appendChild(book);

    就是这样完成的。现在, catalog 元素添加了新的 book 元素。现在剩下的就是写出更新的XML。

    要编写XML,我们需要一个 Transformer 实例,该实例的创建如下所示。请注意,我们要求使用 setOutputProperty()方法缩进输出XML。

    TransformerFactory tfact = TransformerFactory.newInstance();Transformer tform = tfact.newTransformer();tform.setOutputProperty(OutputKeys.INDENT, "yes");tform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");

    生成XML输出的最后一步是应用转换。结果出现在输出流 System.out 上。

    tform.transform(new DOMSource(document), new StreamResult(System.out));

    要将输出直接写入文件,请使用以下命令。

    tform.transform(new DOMSource(document), new StreamResult(new File("output.xml")));

    总结了有关使用DOM API读写XML文件的文章。

    您是否在应用程序中使用过DOM API?它的表现如何?请在下面的评论中告诉我们。

    标签: Java