# 将 DOM 写为 XML 文件

> 原文： [https://docs.oracle.com/javase/tutorial/jaxp/xslt/writingDom.html](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`](../examples/xslt_samples.zip) 并将它们解压缩到 _install-dir_ `/ jaxp-1_4_2-` _ 发布日期 _ `/样本` ] 目录。

* * *

以下代码提供了一个基本模板。它基本上与[文档对象模型](../dom/index.html)课程开头时使用的代码相同。

```
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.FactoryConfigurationError; 
import javax.xml.parsers.ParserConfigurationException; 
import org.xml.sax.SAXException; 
import org.xml.sax.SAXParseException; 

import org.w3c.dom.Document;
import org.w3c.dom.DOMException;

import java.io.*;

public class TransformationApp01 {

    static Document document; 

    public static void main(String argv[]) {
        if (argv.length != 1) {
            System.err.println("Usage: java TransformationApp01 filename");
            System.exit (1);
        }

        DocumentBuilderFactory factory =
        DocumentBuilderFactory.newInstance();

        try {
            File f = new File(argv[0]);
            DocumentBuilder builder =
            factory.newDocumentBuilder();
            document = builder.parse(f);

        } 
        catch (SAXParseException spe) {
            // Error generated by the parser
            System.out.println("\n** Parsing error"
                               + ", line " + spe.getLineNumber()
                               + ", uri " + spe.getSystemId());
            System.out.println("  " + spe.getMessage() );

            // Use the contained exception, if any
            Exception x = spe;
            if (spe.getException() != null)
                x = spe.getException();
            x.printStackTrace();
        }
        catch (SAXException sxe) {
            // Error generated by this application
            // (or a parser-initialization error)
            Exception x = sxe;
            if (sxe.getException() != null)
                x = sxe.getException();
            x.printStackTrace();
        }
        catch (ParserConfigurationException pce) {
            // Parser with specified options 
            // cannot be built
            pce.printStackTrace();
        }
        catch (IOException ioe) {
            // I/O error
            ioe.printStackTrace();
        }
    }
}

```

## 创建一个变压器

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

```
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult;
import java.io.*;

```

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

接下来，添加代码以执行转换：

```
try {
    File f = new File(argv[0]);
    DocumentBuilder builder = factory.newDocumentBuilder();
    document = builder.parse(f);

    // Use a Transformer for output
    TransformerFactory tFactory =
    TransformerFactory.newInstance();
    Transformer transformer = 
    tFactory.newTransformer();

    DOMSource source = new DOMSource(document);
    StreamResult result = new StreamResult(System.out);
    transformer.transform(source, result);
}

```

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

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

* * *

**Note:** 

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

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

```

* * *

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

```
} 
catch (TransformerConfigurationException tce) {
    System.out.println("* Transformer Factory error");
    System.out.println(" " + tce.getMessage());

    Throwable x = tce;
    if (tce.getException() != null)
        x = tce.getException();
    x.printStackTrace(); 
} 
catch (TransformerException te) {
    System.out.println("* Transformation error");
    System.out.println(" " + te.getMessage());

    Throwable x = te;
    if (te.getException() != null)
        x = te.getException();
    x.printStackTrace();
} 
catch (SAXParseException spe) {
    // ...
}

```

**备注**

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

    ```
    import javax.xml.transform.OutputKeys;
    ...
    if (document.getDoctype() != null) {
        String systemValue = (new File (document.getDoctype().getSystemId())).getName();
        transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemValue);
    }

    ```

要了解有关配置工厂和处理验证错误的更多信息，请参阅[将 XML 数据读入 DOM](../dom/readingXML.html) 。

### 运行 `TransformationApp01` 示例

1.  **导航至`样本`目录。**

    ```
    ％cd  install-dir   / jaxp-1_4_2-  释放日期  /样品。 
    ```

2.  **[`Download the XSLT examples by clicking this link`](../examples/xslt_samples.zip) 并将它们解压缩到 _install-dir_ `/ jaxp-1_4_2-` _ 释放日期 _ `/样品`目录。**
3.  **导航到 `xslt` 目录。**

    ```
    % cd xslt

    ```

4.  **Compile the `TransformationApp01` sample.**

    键入以下命令：

    ```
    % javac TransformationApp01.java

    ```

5.  **Run the `TransformationApp01` sample on an XML file.**

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

    ```
    % java TransformationApp01 data/foo.xml

    ```

    您将看到以下输出：

    ```
    &lt;?xml version="1.0" 
        encoding="UTF-8" 
        standalone="no"?&gt;&lt;doc&gt;
      &lt;name first="David" last="Marston"/&gt;
      &lt;name first="David" last="Bertoni"/&gt;
      &lt;name first="Donald" last="Leslie"/&gt;
      &lt;name first="Emily" last="Farmer"/&gt;
      &lt;name first="Joseph" last="Kesselman"/&gt;
      &lt;name first="Myriam" last="Midy"/&gt;
      &lt;name first="Paul" last="Dick"/&gt;
      &lt;name first="Stephen" last="Auriemma"/&gt;
      &lt;name first="Scott" last="Boag"/&gt;
      &lt;name first="Shane" last="Curcuru"/&gt;

    ```

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

## 写出 DOM 的子树

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

* * *

**Note:** 

本节中讨论的代码位于 TranformationApp02.java 中。如果你还没有这样做， [`download the XSLT examples`](../examples/xslt_samples.zip) 并将它们解压缩到 _install-dir_ `/ jaxp-1_4_2-` _ 发布日期 _ ] `/ samples` 目录。

* * *

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

```
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; 

```

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

```
try {
    File f = new File(argv[0]);
    DocumentBuilder builder = factory.newDocumentBuilder();
    document = builder.parse(f);

    NodeList list = document.getElementsByTagName("name");
    Node node = list.item(0); 
}

```

在[创建变换器](#gghgi)中，源对象是通过以下代码行从整个文档构造的

```
DOMSource source = new DOMSource(document);

```

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

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

```

### 运行 `TranformationApp02` 样本

1.  **导航至`样本`目录。**

    ```
    ％cd  install-dir   / jaxp-1_4_2-  释放日期  /样品。 
    ```

2.  **[`Download the XSLT examples by clicking this link`](../examples/xslt_samples.zip) 并将它们解压缩到 _install-dir_ `/ jaxp-1_4_2-` _ 释放日期 _ `/样品`目录。**
3.  **导航到 `xslt` 目录。**

    ```
    cd xslt

    ```

4.  **Compile the `TranformationApp02` sample.**

    键入以下命令：

    ```
    % javac xslt/TranformationApp02.java

    ```

5.  **Run the `TranformationApp02` sample on an XML file.**

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

    ```
    % java TranformationApp02 data/foo.xml

    ```

    您将看到以下输出：

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

    ```

    这次，只有第一个`&lt; name&gt;打印出`元素。

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