XSLT 1.0 - 外部文件查找表

时间:2018-05-02 12:10:08

标签: xml perl xslt

我正在使用Perl和CPAN模块XML::LibXSLT来执行XML转换(因此仅限于XSLT版本1.0)。我对XSLT转换完全不熟悉,但我发现它很有趣并且可能非常强大。我想使用外部文件将数字转换为另一个数字进行查找,但到目前为止,我无法获得所需的结果:

D:\>perl
use warnings;
use strict;
use XML::LibXSLT;
use XML::LibXML;
my $xslt = XML::LibXSLT->new();
my $source = XML::LibXML->load_xml(location => 'invoice.xml');
my $style_doc = XML::LibXML->load_xml(location=>'akv2abz.xsl', no_cdata=>1);
my $stylesheet = $xslt->parse_stylesheet($style_doc);
my $results = $stylesheet->transform($source);
print $stylesheet->output_as_bytes($results);
__END__
compilation error: file akv2abz.xsl element stylesheet
xsl:version: only 1.0 features are supported
<?xml version="1.0"?>
<Invoice>
  <AdditionalDocumentReference>
    <DocumentType>ABZ</DocumentType>
    <ID/>
  </AdditionalDocumentReference>
</Invoice>

预期产出:

<?xml version="1.0"?>
<Invoice>
  <AdditionalDocumentReference>
    <DocumentType>ABZ</DocumentType>
    <ID>ABC123</ID>
  </AdditionalDocumentReference>
</Invoice>

查找文件:

D:\>type lookup.xml
<?xml version="1.0" encoding="utf-8"?>
<QueryResult>
  <Result>
    <ac_name>80186780</ac_name>
    <obj_license>ABC123</obj_license>
  </Result>
  <Result>
    <ac_name>60521933</ac_name>
    <obj_license>DEF567</obj_license>
  </Result>
  <Result>
    <ac_name>60606508</ac_name>
    <obj_license>GHI890</obj_license>
  </Result>
</QueryResult>

源文件:

D:\>type invoice.xml
<?xml version="1.0" encoding="UTF-8"?>
<Invoice>
    <AdditionalDocumentReference>
        <ID>80186780</ID>
        <DocumentType>AKV</DocumentType>
    </AdditionalDocumentReference>
</Invoice>

D:\>

样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:strip-space elements="*"/>
    <xsl:output method="xml" indent="yes"/>

    <xsl:variable name='QueryResult' select='document("lookup.xml")/Result'/>
    <xsl:template match='Invoice'>
        <Invoice>
            <xsl:apply-templates select='AdditionalDocumentReference'/>
        </Invoice>
    </xsl:template>

    <!-- By default, copy everything -->
    <xsl:template match="*|@*|text()|/">
        <xsl:copy>
            <xsl:apply-templates select="*|@*|text()"/>
        </xsl:copy>
    </xsl:template>

    <!-- AdditionalDocumentReference with documentType=AKV should be replaced 
        with AdditionalDocumentReference DocumentType=ABZ and the ID should 
        replaced with the correct obj_license --> 
    <xsl:template match="AdditionalDocumentReference[DocumentType='AKV']"> 
        <xsl:copy>
            <DocumentType>ABZ</DocumentType>
            <ID><xsl:value-of select='$QueryResult[@ac_name=current( )/ID]/@obj_license'/></ID>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

我在这里做点什么吗?

2 个答案:

答案 0 :(得分:3)

如果要使用XSLT 1(并且样式表没有使用任何XSLT 2功能),请在XSLT的mock()version="1.0"根元素上使用xsl:stylesheet代码,因为我认为libxslt否则拒绝运行代码。

此外,如果您想选择元素而不是属性,则需要xsl:transform而非ac_name等路径,以便正确

@ac_name

<xsl:value-of select='$QueryResult[@ac_name=current( )/ID]/@obj_license'/>

另一条路径也是错误的,包含所有更正的完整样式表是

<xsl:value-of select='$QueryResult[ac_name=current( )/ID]/obj_license'/>

答案 1 :(得分:2)

有几种不同版本的XSLT。您的样式表是版本2的风格,

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

但是您用来应用XSLT样式表的Perl模块不支持它。

xsl:version: only 1.0 features are supported

看起来你已经知道了。