写出 DOM 作为 XML 文件
构造 DOM(通过解析 XML 文件或以编程方式构建它)之后,您通常希望将其另存为 XML。本节向您展示如何使用 Xalan 转换包进行此操作。
使用该包,您将创建一个变压器对象,以将DOMSource
连接到StreamResult
。然后,您将调用转换器的transform\(\)
方法以将 DOM 作为 XML 数据写出。
读取 XML
第一步是通过解析 XML 文件在内存中创建 DOM。现在,您应该已经熟悉了该过程。
Note:
本节中讨论的代码在文件TransformationApp01\.java
中。 下载 XSLT 示例并将其解压缩到 install-dir /jaxp\-1_4_2\-
release-date /samples
目录中。
以下代码提供了一个基本的模板。它基本上与文件对象模型类开始时使用的代码相同。
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 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.*;
在这里,您添加了一系列现在应该形成标准 Pattern 的类:一个实体(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:
您可以为变压器对象指定各种输出属性,如 W3C 规范中的http://www.w3.org/TR/xslt#output所定义。例如,要获得缩进输出,可以调用以下方法:
% transformer.setOutputProperty(OutputKeys.INDENT, "yes");
最后,以下突出显示的代码catch了可能产生的新错误:
}
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) {
// ...
}
Notes
-
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。
运行 TransformationApp01 示例
- 导航到
samples
目录.
% cd install-dir/jaxp-1_4_2-release-date/samples.
-
通过单击此链接下载 XSLT 示例并将其解压缩到 install_dir
/jaxp\-1_4_2\-
release-date/samples
目录中. -
导航到
xslt
目录.
% cd xslt
- 编译
TransformationApp01
示例.
键入以下命令:
% javac TransformationApp01.java
- 在 XML 文件上运行
TransformationApp01
示例.
在以下情况下,在解压缩 samples 包后,在xslt/data
目录中的文件foo\.xml
上运行TransformationApp01
。
% java TransformationApp01 data/foo.xml
您将看到以下输出:
<?xml version="1.0"
encoding="UTF-8"
standalone="no"?><doc>
<name first="David" last="Marston"/>
<name first="David" last="Bertoni"/>
<name first="Donald" last="Leslie"/>
<name first="Emily" last="Farmer"/>
<name first="Joseph" last="Kesselman"/>
<name first="Myriam" last="Midy"/>
<name first="Paul" last="Dick"/>
<name first="Stephen" last="Auriemma"/>
<name first="Scott" last="Boag"/>
<name first="Shane" last="Curcuru"/>
如创建一个变压器中所述,此转换器实际上并没有进行任何更改,而是刚刚执行了标识转换,以生成源的副本。实际的转换将在从任意数据结构生成 XML中执行。
写出 DOM 的子树
也可以在 DOM 的子树上进行操作。在本节中,您将try使用该选项。
Note:
本部分讨论的代码在 TranformationApp02.java 中。如果尚未这样做,请下载 XSLT 示例并将其解压缩到 install-dir /jaxp\-1_4_2\-
release-date /samples
目录中。
该过程的唯一区别是,现在您将使用 DOM 中的节点而不是整个 DOM 创建一个DOMSource
。第一步是导入获取所需节点所需的类,如以下突出显示的代码所示:
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
下一步是为实验找到一个好的节点。以下突出显示的代码选择第一个\<name\>
元素。
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);
}
在创建一个变压器中,通过以下代码从整个文档中构造源对象
DOMSource source = new DOMSource(document);
但是,下面突出显示的代码行构造了一个源对象,该源对象由植根于特定节点的子树组成。
DOMSource source = new DOMSource(node);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
运行 TranformationApp02 示例
- 导航到
samples
目录.
% cd install-dir/jaxp-1_4_2-release-date/samples.
-
通过单击此链接下载 XSLT 示例并将其解压缩到 install_dir
/jaxp\-1_4_2\-
release-date/samples
目录中. -
导航到
xslt
目录.
cd xslt
- 编译
TranformationApp02
示例.
键入以下命令:
% javac xslt/TranformationApp02.java
- 在 XML 文件上运行
TranformationApp02
示例.
在以下情况下,在解压缩 samples 包后,在xslt/data
目录中的文件foo\.xml
上运行TranformationApp02
。
% java TranformationApp02 data/foo.xml
您将看到以下输出:
<?xml version="1.0" encoding="UTF-8"
standalone="no"?><doc><name
first="David" last="Marston"/>
这次仅打印了第一个\<name\>
元素。
至此,您已经了解了如何使用转换器写出 DOM,以及如何使用 DOM 的子树作为转换中的源对象。在下一节中,您将看到如何使用转换器从您能够解析的任何数据结构中创建 XML。