您想学习如何从Java读取和写入XML文件吗?
XML文件用于多种目的,包括数据存储。在JSON流行之前,XML是表示,存储和传输结构化数据的首选格式。尽管XML的流行程度近年来有所下降,但您可能偶尔会遇到它,因此从代码中学习如何使用它很重要。
Java Standard Edition(SE)包括 Java XML处理API(JAXP),是涵盖XML处理大部分方面的总称。这些对象包括:
文章中,我们使用 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