首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从XSLT模板调用XSLT函数

从XSLT模板调用XSLT函数
EN

Stack Overflow用户
提问于 2019-05-06 13:43:38
回答 3查看 363关注 0票数 0

我有以下示例xml输入。

代码语言:javascript
复制
<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>

我想生成以下响应消息。

代码语言:javascript
复制
{
"abc" : "2016-07-23"
}

为此,我尝试使用以下xslt。

代码语言:javascript
复制
<?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文档。'/‘的第一个操作数的必需项类型是节点();所提供的值具有项目类型xs:string

我对XSLT不太熟悉。你对这件事有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-05-06 17:42:35

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

代码语言:javascript
复制
<?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>
票数 -1
EN

Stack Overflow用户

发布于 2019-05-06 15:31:08

无法使用提供的XML/XSL输入生成XML文档。'/‘的第一个操作数的必需项类型是节点();所提供的值具有项目类型xs:string ..。你对这件事有什么想法吗?

该消息意味着步骤路径运算符/ 的左手参数必须是节点类型的。因为您已经将$givenDate声明为substring-before(...),所以它将是xs:string类型。因此,在表达式$givenDate/text()中使用它时出现的错误,正如zx485 comment已经指出的那样

我认为最好在函数本身中执行从xs:dateTime到xs:date或'null'的转换,比如在XSLT2.0样式表中:

代码语言:javascript
复制
<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>

输出:

代码语言:javascript
复制
{
"abc": 2016-07-23Z
}

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

票数 0
EN

Stack Overflow用户

发布于 2019-05-06 19:43:03

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

代码语言:javascript
复制
<xsl:function name="ns:set_value" as="xs:string">
   <xsl:param name="givenDate" as="xs:string"/>

有了这些声明,编译器就可以直接告诉您出了什么问题。$givenDate/text()没有意义,因为字符串没有子文本节点;并且返回值

代码语言:javascript
复制
<xsl:text>"</xsl:text>
<xsl:value-of select="$givenDate"/>
<xsl:text>"</xsl:text>

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

代码语言:javascript
复制
<xsl:sequence select='concat("""", $givenDate, """")'/>       

不过,如果您想避免乱搞转义引号,那么另一种选择将是鲜见的。

代码语言:javascript
复制
<xsl:value-of>
    <xsl:text>"</xsl:text>
    <xsl:value-of select="$givenDate"/>
    <xsl:text>"</xsl:text>
</xsl:value-of>

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

代码语言:javascript
复制
<xsl:value-of>"<xsl:value-of select="$givenDate"/>"</xsl:value-of>

或者在XSLT3.0中,使用expand-text="yes"可以使用文本值模板:

代码语言:javascript
复制
<xsl:value-of>"{$givenDate}"</xsl:value-of>          
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56006489

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档