繁体   English   中英

从XSLT模板调用XSLT函数

[英]Call XSLT Function from a XSLT template

我有以下示例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>

我想生成以下响应消息。

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

为此,我尝试使用以下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>

当时我收到以下错误消息。 无法使用提供的XML / XSL输入生成XML文档。 “ /”的第一个操作数的必需项类型是node(); 提供的值的项目类型为xs:string

我对XSLT不太熟悉。 您对这个问题有任何想法吗?

无法使用提供的XML / XSL输入生成XML文档。 “ /”的第一个操作数的必需项类型是node(); 提供的值的项目类型为xs:string

[...]您对这个问题有任何想法吗?

该消息表示步骤路径运算符/左手参数必须为节点类型。 因为您已将$givenDate声明为substring-before(...) ,所以它的类型为xs:string 因此,在表达式$givenDate/text()使用该错误时,该错误已由zx485注释指出

我认为最好像在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>

输出:

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

请注意:如果您有dateTime数据,则强制转换将保留时区信息。

我认为您已经找到了错误,但是错误(或解决问题的难度)的根本原因是无法声明变量和参数的类型。 如果遵循规则,即函数的参数和结果应始终具有声明的类型,那么您将要问自己该函数接受哪种类型的值以及它返回什么,并且您可能会确定输入和输出都是字符串,导致声明:

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

有了这些声明,编译器将能够直接告诉您哪里出了问题。 $givenDate/text()没有意义,因为字符串没有子文本节点。 和返回值

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

这是没有道理的,因为文本节点序列不能转换为字符串。 返回字符串结果的最简单,最直接的方法可能是

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

但是,如果您想避免被转义的引号所困扰,那么另一种方法将是鲜为人知的

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

它将三个文本节点组合为一个(类型声明为=“ xs:string”,然后将文本节点隐式转换为字符串。您也可以将其缩写为

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

或在XSLT 3.0中,通过expand-text="yes"可以使用文本值模板:

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

经过几次尝试,我可以解决问题。

<?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