将 DOM 写为 XML 文件

原文: https://docs.oracle.com/javase/tutorial/jaxp/xslt/writingDom.html

构建 DOM(通过解析 XML 文件或以编程方式构建它)之后,您经常要将其另存为 XML。本节介绍如何使用 Xalan 转换包执行此操作。

使用该包,您将创建一个变换器对象,以将DOMSource连接到StreamResult 。然后,您将调用转换器的transform()方法将 DOM 写为 XML 数据。

阅读 XML

第一步是通过解析 XML 文件在内存中创建 DOM。到现在为止,您应该对这个过程感到满意。


Note:

本节中讨论的代码位于文件TransformationApp01.java中。 Download the XSLT examlles 并将它们解压缩到 install-dir / jaxp-1_4_2- 发布日期 /样例 ] 目录。


以下代码提供了一个基本模板。它基本上与文档对象模型课程开头时使用的代码相同。

  1. import javax.xml.parsers.DocumentBuilder;
  2. import javax.xml.parsers.DocumentBuilderFactory;
  3. import javax.xml.parsers.FactoryConfigurationError;
  4. import javax.xml.parsers.ParserConfigurationException;
  5. import org.xml.sax.SAXException;
  6. import org.xml.sax.SAXParseException;
  7. import org.w3c.dom.Document;
  8. import org.w3c.dom.DOMException;
  9. import java.io.*;
  10. public class TransformationApp01 {
  11. static Document document;
  12. public static void main(String argv[]) {
  13. if (argv.length != 1) {
  14. System.err.println("Usage: java TransformationApp01 filename");
  15. System.exit (1);
  16. }
  17. DocumentBuilderFactory factory =
  18. DocumentBuilderFactory.newInstance();
  19. try {
  20. File f = new File(argv[0]);
  21. DocumentBuilder builder =
  22. factory.newDocumentBuilder();
  23. document = builder.parse(f);
  24. }
  25. catch (SAXParseException spe) {
  26. // Error generated by the parser
  27. System.out.println("\n** Parsing error"
  28. + ", line " + spe.getLineNumber()
  29. + ", uri " + spe.getSystemId());
  30. System.out.println(" " + spe.getMessage() );
  31. // Use the contained exception, if any
  32. Exception x = spe;
  33. if (spe.getException() != null)
  34. x = spe.getException();
  35. x.printStackTrace();
  36. }
  37. catch (SAXException sxe) {
  38. // Error generated by this application
  39. // (or a parser-initialization error)
  40. Exception x = sxe;
  41. if (sxe.getException() != null)
  42. x = sxe.getException();
  43. x.printStackTrace();
  44. }
  45. catch (ParserConfigurationException pce) {
  46. // Parser with specified options
  47. // cannot be built
  48. pce.printStackTrace();
  49. }
  50. catch (IOException ioe) {
  51. // I/O error
  52. ioe.printStackTrace();
  53. }
  54. }
  55. }

创建一个变压器

下一步是创建一个可用于将 XML 传输到System.out的转换器。首先,需要以下 import 语句。

  1. import javax.xml.transform.Transformer;
  2. import javax.xml.transform.TransformerFactory;
  3. import javax.xml.transform.TransformerException;
  4. import javax.xml.transform.TransformerConfigurationException;
  5. import javax.xml.transform.dom.DOMSource;
  6. import javax.xml.transform.stream.StreamResult;
  7. import java.io.*;

在这里,您添加了一系列现在应该形成标准模式的类:实体( Transformer ),创建它的工厂( TransformerFactory ),以及可以的异常由每个人产生。因为转换总是有源和结果,所以然后导入使用 DOM 作为源( DOMSource )所需的类和结果的输出流( StreamResult )。

接下来,添加代码以执行转换:

  1. try {
  2. File f = new File(argv[0]);
  3. DocumentBuilder builder = factory.newDocumentBuilder();
  4. document = builder.parse(f);
  5. // Use a Transformer for output
  6. TransformerFactory tFactory =
  7. TransformerFactory.newInstance();
  8. Transformer transformer =
  9. tFactory.newTransformer();
  10. DOMSource source = new DOMSource(document);
  11. StreamResult result = new StreamResult(System.out);
  12. transformer.transform(source, result);
  13. }

在这里,您创建一个转换器对象,使用 DOM 构造一个源对象,并使用System.out构造一个结果对象。然后告诉变换器对源对象进行操作并输出到结果对象。

在这种情况下,“变压器”实际上并没有改变任何东西。在 XSLT 术语中,您使用的是身份转换,这意味着“转换”会生成源的副本,不会更改。


Note:

您可以为变换器对象指定各种输出属性,如 http://www.w3.org/TR/xslt#output 中的 W3C 规范中所定义。例如,要获取缩进输出,可以调用以下方法:

  1. % transformer.setOutputProperty(OutputKeys.INDENT, "yes");

最后,以下突出显示的代码捕获了可生成的新错误:

  1. }
  2. catch (TransformerConfigurationException tce) {
  3. System.out.println("* Transformer Factory error");
  4. System.out.println(" " + tce.getMessage());
  5. Throwable x = tce;
  6. if (tce.getException() != null)
  7. x = tce.getException();
  8. x.printStackTrace();
  9. }
  10. catch (TransformerException te) {
  11. System.out.println("* Transformation error");
  12. System.out.println(" " + te.getMessage());
  13. Throwable x = te;
  14. if (te.getException() != null)
  15. x = te.getException();
  16. x.printStackTrace();
  17. }
  18. catch (SAXParseException spe) {
  19. // ...
  20. }

备注

  • TransformerExceptions由变换器对象抛出。
  • TransformerConfigurationExceptions由工厂抛出。
  • 要保留 XML 文档的DOCTYPE设置,还需要添加以下代码:

    1. import javax.xml.transform.OutputKeys;
    2. ...
    3. if (document.getDoctype() != null) {
    4. String systemValue = (new File (document.getDoctype().getSystemId())).getName();
    5. transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemValue);
    6. }

要了解有关配置工厂和处理验证错误的更多信息,请参阅将 XML 数据读入 DOM

运行TransformationApp01示例

  1. 导航至样例目录。

    1. cd install-dir / jaxp-1_4_2- 释放日期 /样例。
  2. Download the XSLT examples by clicking this link 并将它们解压缩到 install-dir / jaxp-1_4_2- 释放日期 /样例目录。

  3. 导航到xslt目录。

    1. % cd xslt
  4. Compile the TransformationApp01 sample.

    键入以下命令:

    1. % javac TransformationApp01.java
  5. Run the TransformationApp01 sample on an XML file.

    在下面的例子中, TransformationApp01在解压缩样例包后在xslt / data目录中找到的文件foo.xml上运行。

    1. % java TransformationApp01 data/foo.xml

    您将看到以下输出:

    1. <?xml version="1.0"
    2. encoding="UTF-8"
    3. standalone="no"?><doc>
    4. <name first="David" last="Marston"/>
    5. <name first="David" last="Bertoni"/>
    6. <name first="Donald" last="Leslie"/>
    7. <name first="Emily" last="Farmer"/>
    8. <name first="Joseph" last="Kesselman"/>
    9. <name first="Myriam" last="Midy"/>
    10. <name first="Paul" last="Dick"/>
    11. <name first="Stephen" last="Auriemma"/>
    12. <name first="Scott" last="Boag"/>
    13. <name first="Shane" last="Curcuru"/>

    正如创建变换器中所提到的,这个变换器实际上并没有改变任何东西,而是刚刚执行了身份变换,以生成源的副本。将在从任意数据结构生成 XML 中执行真正的转换。

写出 DOM 的子树

也可以在 DOM 的子树上操作。在本节中,您将尝试该选项。


Note:

本节中讨论的代码位于 TranformationApp02.java 中。如果你还没有这样做, download the XSLT examples 并将它们解压缩到 install-dir / jaxp-1_4_2- 发布日期 ] / samples目录。


该过程的唯一区别是,现在您将使用 DOM 中的节点而不是整个 DOM 创建DOMSource 。第一步是导入获取所需节点所需的类,如以下突出显示的代码所示:

  1. import org.w3c.dom.Document;
  2. import org.w3c.dom.DOMException;
  3. import org.w3c.dom.Node;
  4. import org.w3c.dom.NodeList;

下一步是为实验找到一个好的节点。以下突出显示的代码选择第一个< name>元素。

  1. try {
  2. File f = new File(argv[0]);
  3. DocumentBuilder builder = factory.newDocumentBuilder();
  4. document = builder.parse(f);
  5. NodeList list = document.getElementsByTagName("name");
  6. Node node = list.item(0);
  7. }

创建变换器中,源对象是通过以下代码行从整个文档构造的

  1. DOMSource source = new DOMSource(document);

但是,下面突出显示的代码行构造了一个源对象,该对象由以特定节点为根的子树组成。

  1. DOMSource source = new DOMSource(node);
  2. StreamResult result = new StreamResult(System.out);
  3. transformer.transform(source, result);

运行TranformationApp02样例

  1. 导航至样例目录。

    1. cd install-dir / jaxp-1_4_2- 释放日期 /样例。
  2. Download the XSLT examples by clicking this link 并将它们解压缩到 install-dir / jaxp-1_4_2- 释放日期 /样例目录。

  3. 导航到xslt目录。

    1. cd xslt
  4. Compile the TranformationApp02 sample.

    键入以下命令:

    1. % javac xslt/TranformationApp02.java
  5. Run the TranformationApp02 sample on an XML file.

    在下面的情况中, TranformationApp02在解压缩样例包后,在xslt / data目录中找到的文件foo.xml上运行。

    1. % java TranformationApp02 data/foo.xml

    您将看到以下输出:

    1. &lt;?xml version="1.0" encoding="UTF-8"
    2. standalone="no"?&gt;&lt;doc&gt;&lt;name
    3. first="David" last="Marston"/&gt;

    这次,只有第一个< name&gt;打印出元素。

    此时,您已经了解了如何使用转换器来编写 DOM 以及如何使用 DOM 的子树作为转换中的源对象。在下一节中,您将了解如何使用转换器从您能够解析的任何数据结构中创建 XML。