- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 JAXP 规范 API 与 Saxon-HE API 相结合,主要目的是开发一个应用程序,该应用程序使用可配置的 XSLT 样式表转换 XML 文件,能够覆盖生成的输出文档。我跳过详细信息,因为我创建了一个示例项目来说明遇到的问题:
用例:如果出现转换错误,将 xml 文件移动到另一个目录(可能是错误目录)会引发访问异常。
当我基于 File 实例(指向 XML 文件)实例化 StreamSource 时,如果发生某些解析错误,移动文件会引发“该进程无法访问该文件,因为它正在被另一个进程使用。”异常(exception)。
这是我为说明问题而编写的一个主要单类应用程序:
package com.sample.xslt.application;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.FeatureKeys;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
public class XsltApplicationSample {
public static void main(String[] args) throws Exception {
if (args.length != 2) {
throw new RuntimeException("Two arguments are expected : <xslFilePath> <inputFilePath>");
}
String xslFilePath = args[0];
String xmlFilePath = args[1];
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(FeatureKeys.ALLOW_MULTITHREADING, Boolean.TRUE);
factory.setAttribute(FeatureKeys.RECOVERY_POLICY,
new Integer(Configuration.RECOVER_WITH_WARNINGS));
Source xslSource = new StreamSource(new File(xslFilePath));
Source xmlSource = new StreamSource(new File(xmlFilePath));
Transformer transformer = factory.newTransformer(xslSource);
try {
transformer.transform(xmlSource, new DOMResult());
} catch (TransformerException e) {
System.out.println(e.getMessage());
}
// move input file to tmp directory (for example, could be configured error dir)
File srcFile = Paths.get(xmlFilePath).toFile();
File tempDir = new File(System.getProperty("java.io.tmpdir"));
Path destFilePath = new File(tempDir, srcFile.getName()).toPath();
try {
Files.move(srcFile.toPath(), destFilePath, StandardCopyOption.REPLACE_EXISTING);
} catch (SecurityException | IOException e) {
System.out.println(e.getMessage());
}
}
}
配置的 xslt 转换文件内容必须有效才能重现。如果输入的xml文件为空,则会产生转换/解析错误,但不会发生访问文件错误。
要重现的输入文件示例:
<root>
<elem>
</root>
标准输出示例:
JAXP: find factoryId =javax.xml.transform.TransformerFactory
JAXP: find factoryId =javax.xml.parsers.SAXParserFactory
JAXP: loaded from fallback value: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
JAXP: created new instance of class com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl using ClassLoader: null
JAXP: find factoryId =javax.xml.parsers.SAXParserFactory
JAXP: loaded from fallback value: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
JAXP: created new instance of class com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl using ClassLoader: null
JAXP: find factoryId =javax.xml.parsers.DocumentBuilderFactory
JAXP: loaded from fallback value: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
JAXP: created new instance of class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl using ClassLoader: null
JAXP: find factoryId =javax.xml.parsers.SAXParserFactory
JAXP: loaded from fallback value: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
JAXP: created new instance of class com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl using ClassLoader: null
Error on line 3 column 3 of input_err.xml:
SXXP0003: Error reported by XML parser: The element type "elem" must be terminated by the
matching end-tag "</elem>".
org.xml.sax.SAXParseException; systemId: file:/C:/<path>/input_err.xml; lineNumber: 3; columnNumber: 3; The element type "elem" must be terminated by the matching end-tag "</elem>".
C:\<path>\input_err.xml -> C:\<path>\AppData\Local\Temp\input_err.xml: The process cannot access the file because it is being used by another process.
使用命令行(我使用 Eclipse):
java ... -Djaxp.debug=1 -Dfile.encoding=UTF-8 -classpath <...> com.sample.xslt.application.XsltApplicationSample C:\<path>\transform.xsl C:\<path>\input_err.xml
使用的pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>XsltExampleProject</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>XsltExampleProject</name>
<description>XSLT example project</description>
<dependencies>
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>9.7.0-7</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
我使用的解决方法是将 xml 输入文件的内容作为字符串加载到内存中,请参阅以下内容:
String xmlContent = FileUtils.readFileToString(new File(xmlFilePath), StandardCharsets.UTF_8);
Source xslSource = new StreamSource(new File(xslFilePath));
Source xmlSource = new StreamSource(new StringReader(xmlContent));
初始化 Transformer 时我错过了什么吗?默认解析的 SAX 解析器应该重写为 Saxon 推荐的另一个 API?我认为Xerces解析器是根据调试日志记录使用的,但是它与Saxon提供的变压器实现完全兼容吗?我对这个有点困惑..
感谢您的帮助!
最佳答案
从问题后面的评论线程来看,这似乎是 JDK 提供的 XML 解析器中的错误/缺陷。您的选择是:
(a) 报告错误并耐心等待修复
(b) 使用 Apache Xerces 解析器
(c) 不提供 File,而是提供 FileInputStream,然后自行关闭它。
我的建议是 (b),因为 Apache Xerces 解析器比 JDK 中的版本可靠得多。
关于java - JAXP 撒克逊-he : XMLfile StreamSource doesn't release file access after parsing error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39230817/
我有一个 JSP,它将 XSL 附加到从数据库中提取的 XML 文档。该应用程序正在使用 Saxon 解析器,但我的 XML 需要使用 Xalan 解析器。 JSP 页面可以覆盖要使用的解析器吗? 最
我们最近更新了我们的 Tomcat 网络服务。我们唯一真正更新的是我们将 XMLBeans 更新到 2.4 版,将 Saxon 更新到版本 9。 运行 Netbeans 和 eclipse,我们的项目
我尝试使用 Altova Map Force 中生成的 XSLT 将一个 XML 文件 XSLT 转换为另一个 XML。 起初,当 saxon 处理器找不到此处描述的 Altova 特定功能时,我遇到
当我运行 XQuery 命令行时,只要结果是一个元素,它就可以工作。 当我扩展该 XQuery 以仅获取属性值时,它会失败并出现以下错误: SENR0001: Cannot serialize a f
我想通过 Java Saxon API 修改 XML 文档。 我从 DocumentInfo 开始,深入到我想要更改的 NodeInfo-s。这很好用。但是,我没有找到允许我更改这些节点属性的 API
我有一个定义了多个函数的 XSL。 我想编写 Java 代码,它采用 XSL 函数的名称(和参数列表)并运行该函数(当然,还将参数绑定(bind)到函数的形式参数)。 到目前为止,我唯一的解决方案是使
我正在使用 Saxon HE 9.5.1.8 将 XML 转换为另一个 XML 文件。 我的问题是,由 Saxon 的 Serializer() 类编写的 XML 内容会打印出几个我不想在其中出现的额
我的公司在我们的产品中大量使用 XSLT,并且我们即将从 Java 的 javax.xml API 迁移到 Saxon 的 s9api。因此,我的任务是探索新的 API 并找出我们需要进行哪些更改。
我想对多个输出文件进行 XSLT 转换。我在那里使用了“xsl:结果文档”。当转换失败时,应删除所有输出文件。但是,如果由“xsl:result-document”创建的文档生成失败,我的程序将无法再
我有一个简单的 jar 测试程序,我用它来通过 xquery 文件解析 xml。问题是在 xquery 文件中我声明了一个 java 命名空间: declare namespace java="jav
我正在使用 JAXP 规范 API 与 Saxon-HE API 相结合,主要目的是开发一个应用程序,该应用程序使用可配置的 XSLT 样式表转换 XML 文件,能够覆盖生成的输出文档。我跳过详细信息
我使用 Saxon(Java) 将 *.xhtml 转换为 *.xml。 这是我的java代码: System.setProperty("javax.xml.transform.Transformer
我使用 Saxon HE 9.2 进行一些 XSLT 转换,随后由 Castor 1.3.1 对输出进行解码。整个过程都在 JDK 6 上使用 Java 运行。 我的 XSLT 转换如下所示:
我有以下 XSLT 2.0 模板: .. 我正在努力以编程方式提供 currentTotal 作为变压器的参数,如下所示: transformer.setParameter("currentTo
我正在尝试从 Xalan 迁移到 Saxon(为了 xslt 2.0 支持)并且遇到以下异常。我已确保环境中不再有所有 Xalan jar ,现在包括一些 Saxon 9.1.0.8 jar 。 转换
我是一名优秀的程序员,十分优秀!