【问题标题】:How to resolve XInclude instructions in a XML file from command line with XSLT 3.0如何使用 XSLT 3.0 从命令行解析 XML 文件中的 XInclude 指令
【发布时间】:2019-12-10 23:22:49
【问题描述】:

我们的 XML 数据存储在单独的文件中,因此人员可以单独处理简单的模块。将单独的文件组合成一个主文件以进行进一步处理。目前我正在 Oxygen XML 编辑器的 IDE 中执行此操作。为了简化这个过程,我想在没有这个 IDE 的情况下从命令行进行。如何使用 Saxon HE 从命令行解析 XInclude 语句(如果可能的话)?

我试过这样的命令:

java -jar saxon9he.jar -xi:on -s:main.xml -xsl:assemble.xslt -o:master.xml -t

并得到以下错误代码:

Saxon-HE 9.9.1.4J from Saxonica
Java version 1.8.0_191
Stylesheet compilation time: 361.152836ms
Processing file:/u:/Wolke/xml/resolve-xi/main.xml
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:/u:/Wolke/xml/resolve-xi/main.xml using class net.sf.saxon.tree.tiny.TinyBuilder
Exception in thread "main" java.lang.StackOverflowError
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.org.apache.xerces.internal.utils.SecuritySupport.getContextClassLoader(Unknown Source)
        at com.sun.org.apache.xerces.internal.utils.ObjectFactory.findClassLoader(Unknown Source)
        at com.sun.org.apache.xerces.internal.utils.ObjectFactory.newInstance(Unknown Source)
        at com.sun.org.apache.xerces.internal.xinclude.XIncludeHandler.handleIncludeElement(Unknown Source)
        at com.sun.org.apache.xerces.internal.xinclude.XIncludeHandler.emptyElement(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
[and many more lines]

Saxonica 的关于 xi:on 参数的文档说:“将 XInclude 处理应用于所有输入 XML 文档(包括模式和样式表模块以及源文档)。目前这仅在使用 Xerces 解析器解析文档时有效,这是JDK 1.5 及更高版本中的默认值。” (https://www.saxonica.com/documentation9.5/using-xsl/commandline.html) -- 不知道这是什么意思。

主 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>

<TEI xmlns="http://www.tei-c.org/ns/1.0">
    <teiHeader xml:id="header">
        <fileDesc>
            <titleStmt><title>Trying to make XInclude work</title></titleStmt>
            <publicationStmt><p>Sample data for stackoverflow question</p></publicationStmt>
            <sourceDesc><p>Just made up</p></sourceDesc>
        </fileDesc>
    </teiHeader>
    <text>
        <body>
            <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="file1.xml" xpointer="content-p1"/>
            <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="file2.xml" xpointer="content-p2"/>
            <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="file3.xml" xpointer="content-p3"/>
        </body>
    </text>
</TEI>

XML 组件文件:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml"
    schematypens="http://purl.oclc.org/dsdl/schematron"?>
<?xml-stylesheet type="text/css" href="../css/mm-xml.css"?>

<TEI xmlns="http://www.tei-c.org/ns/1.0">
    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="main.xml" xpointer="header"/>
    <text>
        <body>
            <div type="page" xml:id="content-p1">
                <p> Integer sit amet justo porta nisl porta aliquet in a justo.</p>
            </div>
        </body>
    </text>
</TEI>
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml"
    schematypens="http://purl.oclc.org/dsdl/schematron"?>
<?xml-stylesheet type="text/css" href="../css/mm-xml.css"?>

<TEI xmlns="http://www.tei-c.org/ns/1.0">
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="main.xml" xpointer="header"/>
   <text>
      <body>
         <div type="page" xml:id="content-p2">
            <p>Quisque gravida venenatis varius.</p>
         </div>
      </body>
   </text>
</TEI>
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml"
    schematypens="http://purl.oclc.org/dsdl/schematron"?>
<?xml-stylesheet type="text/css" href="../css/mm-xml.css"?>

<TEI xmlns="http://www.tei-c.org/ns/1.0">
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="main.xml" xpointer="header"/>
   <text>
      <body>
         <div type="page" xml:id="content-p3">
            <p>Nullam nisi lacus, malesuada vel eros porta, dictum finibus mauris.</p>
         </div>
      </body>
   </text>
</TEI>

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

我需要的输出(就像 Oxygen IDE 创建它一样):

<?xml version="1.0" encoding="UTF-8"?><?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?><?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
    <teiHeader xml:id="header">
        <fileDesc>
            <titleStmt>
                <title>Trying to make XInclude work</title>
            </titleStmt>
            <publicationStmt>
                <p>Sample data for stackoverflow question</p>
            </publicationStmt>
            <sourceDesc>
                <p>Just made up</p>
            </sourceDesc>
        </fileDesc>
    </teiHeader>
    <text>
        <body>
            <div type="page" xml:id="content-p1" xml:base="file1.xml">
                <p> Integer sit amet justo porta nisl porta aliquet in a justo.</p>
            </div>
            <div type="page" xml:id="content-p2" xml:base="file2.xml">
                <p>Quisque gravida venenatis varius.</p>
            </div>
            <div type="page" xml:id="content-p3" xml:base="file3.xml">
                <p>Nullam nisi lacus, malesuada vel eros porta, dictum finibus mauris.</p>
            </div>
        </body>
    </text>
</TEI>

【问题讨论】:

  • 请使用 -t 选项运行 Saxon,并将 Saxon 和 Java JRE 的确切版本输出添加到您的问题描述中。
  • 我无法解释您显示的堆栈跟踪,但在 Saxon 9.9.1.4 HE 和 JRE 1.8 的本地测试中,Xerces 作为 XML 解析器似乎支持 XInclude 指令,但不支持任何 xml:id基于xpointer 参考。这似乎符合xerces.apache.org/xerces2-j/faq-xinclude.html#faq-8。我不确定 oXygen 是如何实现它们的工作的,如果他们有特殊版本的 Xerces 或某些特定配置以使基于 xml:idxpointer 参考工作正常,这可能有助于询问他们的支持。
  • 感谢 Martin Honnen 的反馈,我添加了 -t 参数并相应地编辑了问题描述。
  • 没想到Xerces不支持xpointer()函数,谢谢提示,求支持。
  • 似乎 Xerces 支持 xpointer="some-id" 如果您包含的文档具有基于 DTD 的元​​素声明,该元素具有声明为 ID 类型的特定属性和值 some-id 但不知何故 @987654339不支持基于 @ 的声明。

标签: xml xslt saxon xerces xinclude


【解决方案1】:

根据我们对 cme​​ts 的交流以及您从 oXygen 支持中获得的建议,看起来像使用 oXygen 的 Xerces 补丁版本(可在 https://mvnrepository.com/artifact/com.oxygenxml/oxygen-patched-xerces/21.1.0.2 获得)与 Saxon 9.9 一起使用,他应该能够启用基于 xpointer 的 XInclude from @ 987654323@属性:

java -cp 'oxygen-patched-xerces-21.1.0.2.jar;saxon9he.jar' net.sf.saxon.Transform -t -s:input.xml -xsl:sheet.xsl -xi:on

这是我在 Windows 10 Powershell 窗口中使用和测试的命令行,根据平台和命令行 shell,您可能需要为 -cp 参数使用不同的引号字符,并在不同的 jar 之间使用不同的项目分隔符那里列出的文件。

【讨论】:

  • 刚刚意识到 Bash Shell 使用冒号作为路径分隔符。所以使用 Bash 命令会是:java -cp 'oxygen-patched-xerces-21.1.0.2.jar:saxon9he.jar' net.sf.saxon.Transform -t -s:input.xml -xsl:sheet.xsl -xi:on
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 2019-04-09
  • 2013-07-12
  • 2016-12-09
  • 2023-03-23
相关资源
最近更新 更多