简体   繁体   English

从XSLT模板调用XSLT函数

[英]Call XSLT Function from a XSLT template

I have the following sample xml input. 我有以下示例xml输入。

<RootElement xmlns="http://example.com">
<aa>test</aa>
<bb>ffff</bb>
<cc>dere</cc>
<givenDate>2016-07-23T00:00:00.000+00:00</givenDate>
</RootElement>

I want to generate the following response message. 我想生成以下响应消息。

{
"abc" : "2016-07-23"
}

For that I tried to use the following xslt. 为此,我尝试使用以下xslt。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://example.com" version="1.0" exclude-result-prefixes="ns">
    <xsl:output method="text" omit-xml-declaration="yes" indent="no" encoding="UTF-8" media-type="application/json"/>
    <xsl:template match="/">
        <xsl:text>{</xsl:text>

        <xsl:text>"abc": </xsl:text>
        <xsl:variable name="givenDate" select="substring-before(//ns:RootElement/ns:givenDate, 'T')"/>
        <xsl:value-of select="ns:set_value($givenDate)"/>

        <xsl:text>}</xsl:text>
    </xsl:template> 

    <xsl:function name="ns:set_value">
        <xsl:param name="givenDate"/>
        <xsl:choose>
            <xsl:when test="$givenDate/text() !=''">
                <xsl:text>"</xsl:text><xsl:value-of select="$givenDate"/><xsl:text>"</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>null</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>

</xsl:stylesheet>

At that time I'm getting below error message. 当时我收到以下错误消息。 Unable to generate the XML document using the provided XML/XSL input. 无法使用提供的XML / XSL输入生成XML文档。 Required item type of first operand of '/' is node(); “ /”的第一个操作数的必需项类型是node(); supplied value has item type xs:string 提供的值的项目类型为xs:string

I'm not much familiar with XSLT. 我对XSLT不太熟悉。 Do you have any idea about the issue? 您对这个问题有任何想法吗?

Unable to generate the XML document using the provided XML/XSL input. 无法使用提供的XML / XSL输入生成XML文档。 Required item type of first operand of '/' is node(); “ /”的第一个操作数的必需项类型是node(); supplied value has item type xs:string 提供的值的项目类型为xs:string

[...] Do you have any idea about the issue? [...]您对这个问题有任何想法吗?

The message means that left hand argument for step path operator / must be of node type. 该消息表示步骤路径运算符/左手参数必须为节点类型。 Because you have declared $givenDate as substring-before(...) , it would be of type xs:string . 因为您已将$givenDate声明为substring-before(...) ,所以它的类型为xs:string Thus the error when you use it in the expression $givenDate/text() , as already pointed by zx485 comment 因此,在表达式$givenDate/text()使用该错误时,该错误已由zx485注释指出

I think that it would be better to perform such conversion from xs:dateTime to xs:date or 'null' in the function itself like in this XSLT 2.0 stylesheet: 我认为最好像在XSLT 2.0样式表中那样,在函数本身中执行从xs:dateTime到xs:date或'null'转换:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ns="http://example.com" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="ns xs">
    <xsl:output method="text" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <xsl:text>{&#xA;"abc": </xsl:text>
        <xsl:value-of select="ns:set_value(//ns:RootElement/ns:givenDate)"/>
        <xsl:text>&#xA;}</xsl:text>
    </xsl:template> 

    <xsl:function name="ns:set_value">
        <xsl:param name="givenDate"/>
        <xsl:sequence 
            select="if ($givenDate castable as xs:dateTime)
                    then xs:date(xs:dateTime($givenDate))
                    else 'null'"/>
    </xsl:function>
</xsl:stylesheet>

Output: 输出:

{
"abc": 2016-07-23Z
}

Do note: if you have a dateTime data, the casting wiil retain timezone information. 请注意:如果您有dateTime数据,则强制转换将保留时区信息。

I think you've found the error, but the root cause of the error (or of your difficulty in solving it) is the failure to declare the types of your variables and parameters. 我认为您已经找到了错误,但是错误(或解决问题的难度)的根本原因是无法声明变量和参数的类型。 If you followed the rule that parameters and results of functions should always have a declared type, then you would have asked yourself what kind of value the function accepts and what it returns, and you would probably have decided that the input and output are both strings, leading to the declaration: 如果遵循规则,即函数的参数和结果应始终具有声明的类型,那么您将要问自己该函数接受哪种类型的值以及它返回什么,并且您可能会确定输入和输出都是字符串,导致声明:

<xsl:function name="ns:set_value" as="xs:string">
   <xsl:param name="givenDate" as="xs:string"/>

With these declarations, the compiler would be able to tell you directly what is wrong. 有了这些声明,编译器将能够直接告诉您哪里出了问题。 $givenDate/text() doesn't make sense because a string doesn't have child text nodes; $givenDate/text()没有意义,因为字符串没有子文本节点。 and the return value 和返回值

<xsl:text>"</xsl:text>
<xsl:value-of select="$givenDate"/>
<xsl:text>"</xsl:text>

doesn't make sense because a sequence of text nodes can't be converted to a string. 这是没有道理的,因为文本节点序列不能转换为字符串。 The simplest and most direct way to return the string result is probably 返回字符串结果的最简单,最直接的方法可能是

<xsl:sequence select='concat("""", $givenDate, """")'/>       

though if you want to avoid messing about with escaped quotes then an alternative would be the rarely-seen 但是,如果您想避免被转义的引号所困扰,那么另一种方法将是鲜为人知的

<xsl:value-of>
    <xsl:text>"</xsl:text>
    <xsl:value-of select="$givenDate"/>
    <xsl:text>"</xsl:text>
</xsl:value-of>

which combines three text nodes into one (and the type declaration as="xs:string" then causes implicit conversion of the text node to a string. You could also abbreviate this to 它将三个文本节点组合为一个(类型声明为=“ xs:string”,然后将文本节点隐式转换为字符串。您也可以将其缩写为

<xsl:value-of>"<xsl:value-of select="$givenDate"/>"</xsl:value-of>

Or in XSLT 3.0, with expand-text="yes" you could use a text value template: 或在XSLT 3.0中,通过expand-text="yes"可以使用文本值模板:

<xsl:value-of>"{$givenDate}"</xsl:value-of>          

After trying several time, I could resolve the issue. 经过几次尝试,我可以解决问题。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://example.com" version="1.0" exclude-result-prefixes="ns"  xmlns:func="http://exslt.org/functions">
    <xsl:output method="text" omit-xml-declaration="yes" indent="no" encoding="UTF-8" media-type="application/json"/>
    <xsl:template match="/">
        <xsl:text>{</xsl:text>
        <xsl:text>"abc": </xsl:text>
        <xsl:variable name="givenDate" select="substring-before(//ns:RootElement/ns:givenDate, 'T')"/>

        <xsl:value-of select="ns:set_value($givenDate)"/>

        <xsl:text>}</xsl:text>
    </xsl:template> 

    <xsl:function name="ns:set_value">
        <xsl:param name="givenDate"/>
        <xsl:choose>
            <xsl:when test="$givenDate !=''">
 <func:result>
<xsl:text>"</xsl:text>
                <xsl:value-of select="$givenDate"/>
<xsl:text>"</xsl:text>
 </func:result>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>null</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>

</xsl:stylesheet>

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM