简体   繁体   English

使用 Saxon 的 XSLT 引擎处理 XML 时,如何将我的 XSL 文件指向它所需的 XSD 文件?

[英]When processing XML with Saxon's XSLT engine, how can I point my XSL file to the XSD file it requires?

Here is the folder structure of my project.这是我的项目的文件夹结构。

src/main
├── assembly
│   └── package.xml
├── java
│   └── org
│       └── legible
│           ├── kafka
│           │   ├── CamelSftpSourceConnector.java
│           │   ├── CamelSftpSourceConnectorConfig.java
│           │   ├── CamelSftpSourceTask.java
│           │   ├── CamelSourceTask.java
│           │   └── package-info.java
│           └── reference_tag_converter
│               └── ReferenceTagTransformer.java
└── resources
    ├── schemas
    │   ├── ONIX_BookProduct_3.0_reference.xsd
    │   ├── ONIX_BookProduct_3.0_short.xsd
    │   ├── ONIX_BookProduct_CodeLists.xsd
    │   └── ONIX_XHTML_Subset.xsd
    ├── switch-onix-3.0-tagnames-2.0_v1.3.xsl
    └── switch-onixmessage-tag.xsl   

Inside of ReferenceTagTransformer , I'm instantiating an XSLT transformer as follows:ReferenceTagTransformer内部,我正在实例化一个 XSLT 转换器,如下所示:



        StreamSource switchOnixMessageTagStylesheet = new StreamSource(this.getClass().getClassLoader().getResourceAsStream("switch-onixmessage-tag.xsl"));
        StreamSource transformReferenceTagStylesheet = new StreamSource(this.getClass().getClassLoader().getResourceAsStream("switch-onix-3.0-tagnames-2.0_v1.3.xsl"));

        Processor processor = new Processor(false);

        XsltCompiler compiler = processor.newXsltCompiler();

        XsltExecutable switchOnixMessageStylesheet = compiler.compile(switchOnixMessageTagStylesheet);
        XsltTransformer onixMessageTagTransformer = switchOnixMessageStylesheet.load();

        XsltExecutable convertTagsStylesheet = compiler.compile(transformReferenceTagStylesheet);
        XsltTransformer referenceTagTransformer = convertTagsStylesheet.load();

        referenceTagTransformer.setParameter(new QName("result-document"), new XdmAtomicValue(Paths.get("", "temp.xml").toString()));

        // path to XSD schemas
        referenceTagTransformer.setParameter(new QName("input-path"), new XdmAtomicValue("schemas"));

When I call transform on the transformer, I get an error that comes from the stylesheet saying that it cannot resolve the path to schemas , which is assigned to the input-path variable in my code above.当我在transform上调用transform时,我收到来自样式表的错误,说它无法解析schemas的路径,该input-path在我上面的代码中分配给input-path变量。

How can I set the input-path parameter on the referenceTagTransformer such that the XSL stylesheet I've loaded can find schemas in the appropriate place?如何在referenceTagTransformer上设置input-path参数,以便我加载的 XSL 样式表可以在适当的位置找到schemas

Any advice would be very helpful.任何建议都会非常有帮助。 Thank you very much in advance!非常感谢您提前!

Here's the contents of the stylesheet for reference:以下是样式表的内容供参考:

<?xml version="1.0" encoding="UTF-8"?>
<!-- switch ONIX tagnames for ONIX 3.0, XSLT 2.0 -->
<!-- © EDitEUR, licence doi:https://doi.org/10.4400/nwgj -->
<!-- version 1.1, modified to deal with XHTML markup -->
<!-- version 1.2, modified to deal with xmlns attribute in root element -->
<!-- version 1.3, modified to use XSD schema when available -->
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://ns.editeur.org/">
    <xsl:param name="input-path" required="yes"/>
    <xsl:param name="result-document" required="yes"/>
    <xsl:param name="dtd-path" select="''"/>
    <xsl:variable name="new-namespace">
        <xsl:choose>
            <xsl:when test="local-name(/*)='ONIXMessage'">
                <xsl:value-of select="replace(namespace-uri(/*),'/reference','/short')"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="replace(namespace-uri(/*),'/short','/reference')"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="release" select="/*/@release"/>
    <xsl:variable name="input-path-cleaned" select="translate(replace($input-path,' ','%20'),'\','/')"/>
    <xsl:variable name="xsd-path" select="tokenize(/*/@xsi:schemaLocation,' ')[2]"/>
    <xsl:variable name="xsd-path-absolute">
        <xsl:call-template name="make-absolute-xsd-path">
            <xsl:with-param name="input-path" select="$input-path-cleaned"/>
            <xsl:with-param name="xsd-path" select="$xsd-path"/>
        </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="xsd-content">
        <xsl:if test="$xsd-path!=''">
            <xsl:copy-of select="document($xsd-path-absolute)"/>
        </xsl:if>
    </xsl:variable>
    <xsl:variable name="target">
        <xsl:choose>
            <!-- v1.1 was xsl:when test="/ONIXMessage">short</xsl:when -->
            <xsl:when test="local-name(/*)='ONIXMessage'">short</xsl:when>
            <xsl:otherwise>reference</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:template match="/">
        <xsl:choose>
            <xsl:when test="/*[not(@refname or @shortname)] and count($xsd-content/*) = 0">
                <xsl:message>TRANSFORMATION ABORTED! No XSD schema or DTD found!</xsl:message>
            </xsl:when>
            <xsl:when test="not($dtd-path='')">
                <xsl:result-document href="{$result-document}" method="xml" doctype-system="{$dtd-path}">
                    <xsl:apply-templates/>
                </xsl:result-document>
            </xsl:when>
            <xsl:otherwise>
                <xsl:result-document href="{$result-document}" method="xml" exclude-result-prefixes="xs">
                    <xsl:apply-templates/>
                </xsl:result-document>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="*">
        <xsl:variable name="target-name">
            <xsl:choose>
                <xsl:when test="$target='short' and $xsd-content//xs:element[@name=local-name(current())]">
                    <xsl:value-of select="$xsd-content//xs:element[@name=local-name(current())]//xs:attribute[@name='shortname']//xs:enumeration/@value"/>
                </xsl:when>
                <xsl:when test="$target='short' and not(@shortname)">
                    <xsl:value-of select="name()"/>
                </xsl:when>
                <xsl:when test="$target='short'">
                    <xsl:value-of select="@shortname"/>
                </xsl:when>
                <xsl:when test="$xsd-content//xs:element[@name=local-name(current())]">
                    <xsl:value-of select="$xsd-content//xs:element[@name=local-name(current())]//xs:attribute[@name='refname']//xs:enumeration/@value"/>
                </xsl:when>
                <xsl:when test="not(@refname)">
                    <xsl:value-of select="name()"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="@refname"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:element name="{$target-name}" namespace="{$new-namespace}">
            <xsl:for-each select="@*">
                <xsl:choose>
                    <xsl:when test="name()='refname' or name()='shortname'"/>
                    <xsl:when test="name()='xsi:schemaLocation' and $target='short'">
                        <xsl:attribute name="xsi:schemaLocation">
                            <xsl:value-of select="replace(.,'(/|_)reference','$1short')"/>
                        </xsl:attribute>
                    </xsl:when>
                    <xsl:when test="name()='xsi:schemaLocation'">
                        <xsl:attribute name="xsi:schemaLocation">
                            <xsl:value-of select="replace(.,'(/|_)short','$1reference')"/>
                        </xsl:attribute>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:copy-of select="."/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
            <xsl:apply-templates select="*|text()"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="text()">
        <xsl:copy/>
    </xsl:template>
    <xsl:template name="make-absolute-xsd-path">
        <xsl:param name="input-path"/>
        <xsl:param name="xsd-path"/>
        <xsl:choose>
            <xsl:when test="starts-with($xsd-path,'file:/') and contains('ABCDEFGHIJKLMNOPQRSTUVWXYZ',substring($xsd-path,7,1)) and substring($xsd-path,8,1)=':'">
                <xsl:value-of select="concat('///',substring-after($xsd-path,'file:/'))"/>
            </xsl:when>
            <xsl:when test="starts-with($xsd-path,'file:/')">
                <xsl:value-of select="substring-after($xsd-path,'file:')"/>
            </xsl:when>
            <xsl:when test="starts-with($xsd-path,'/')">
                <xsl:value-of select="$xsd-path"/>
            </xsl:when>
            <xsl:when test="starts-with($xsd-path,'./')">
                <xsl:value-of select="concat($input-path,substring-after($xsd-path,'.'))"/>
            </xsl:when>
            <xsl:when test="starts-with($xsd-path,'../')">
                <xsl:variable name="new-input-path">
                    <xsl:call-template name="remove-input-path-segment">
                        <xsl:with-param name="input-path" select="$input-path"/>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:call-template name="make-absolute-xsd-path">
                    <xsl:with-param name="input-path" select="$new-input-path"/>
                    <xsl:with-param name="xsd-path" select="substring-after($xsd-path,'../')"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="concat($input-path,'/',$xsd-path)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="remove-input-path-segment">
        <xsl:param name="input-path"/>
        <xsl:param name="in-path" select="false()"/>
        <xsl:if test="contains($input-path,'/')">
            <xsl:if test="$in-path=true()">/</xsl:if>
            <xsl:value-of select="substring-before($input-path,'/')"/>
            <xsl:call-template name="remove-input-path-segment">
                <xsl:with-param name="input-path" select="substring-after($input-path,'/')"/>
                <xsl:with-param name="in-path" select="true()"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

The problem is that when executing this line问题是在执行这一行时

XsltExecutable switchOnixMessageStylesheet = compiler.compile(switchOnixMessageTagStylesheet);

the XSLT compiler just reads a byte stream. XSLT 编译器只是读取一个字节流。 It does not know where those bytes came from.它不知道这些字节来自哪里。 It could be a file in some directory, it could come from the classpath, it could even come from the network.它可能是某个目录中的文件,可能来自类路径,甚至可能来自网络。 Your code though should know where the data came from.你的代码虽然应该知道数据来自哪里。

Inside the XSLT the schema and other stylesheets are referenced via URIs.在 XSLT 中,模式和其他样式表是通过 URI 引用的。 All you need to do is give the compiler a URI resolver via setURIResolver() .您需要做的就是通过setURIResolver()为编译器提供一个 URI 解析器。 Your code knows where the stylesheet came from, so you should know how where to lookup the dependencies.您的代码知道样式表来自哪里,因此您应该知道如何查找依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Saxon s9api进行XSLT 2.0转换? XML文件到XML文件 - How to do XSLT 2.0 transform using saxon s9api? XML file to XML file 如何使用带有 xslt 的撒克逊文件将 output 指定为 xml 文件? - How to specify output to an xml file using saxon with xslt? 使用xml和xsl文件(xslt 2.0)创建html文件时出错(XML解析器处理报告的可恢复错误I / O错误) - Errors creating html file using xml and xsl file (xslt 2.0) (Recoverable error I/O error reported by XML parser processing) 使用 Saxon 对 Mei 文件 (xml) 运行 XSL 转换 - Run XSL tranformation on an Mei file(xml) Using Saxon 使用Saxon-HE在JavaFX中对xml文件进行XSLT转换 - XSLT transformation of xml file in JavaFX with Saxon-HE Saxon XML验证:验证失败时无法删除XML文件 - Saxon XML Validation: Cannot delete XML File, when validation failed 如何使用Saxon XSLT转换每个xml节点? - How to transform each xml node with Saxon XSLT? JAXB:当使用XML模式(.xsd)验证XML文件时,如果验证失败,我可以知道导致它的XML标记吗? - JAXB: when using XML schema (.xsd) to validate an XML file, if validation fail, can I know which XML tag causing it? Saxon XSLT转换为字符串而不是文件 - Saxon XSLT Transform to String Instead of File 我可以针对Java中的XSD片段验证XML文件吗? - Can I validade a XML file against XSD fragment in Java
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM