使用xslt 2.0执行转换如何使用分隔符分隔引用的值?

时间:2017-03-20 19:13:43

标签: xml xslt xslt-2.0 transformation saxon

我有一个要转换的xml:

<root>
  <item name="first" />
  <item name="second" />
  <item name="third" />
</root>

我想得到的是一个字符串,其中引用了每个值并且值是分开的(顺序无关紧要):

"first" , "second" , "third"

我的问题是如何正确使用xslt 2.0实现这一目标?

这是我的解决方案无法按预期工作。 所以我的共同问题是 - 为什么不是?

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns="urn:my.name.space"
    version="2.0">

  <xsl:output method="text" media-type="text/json"/>

  <xsl:template match="root">
    <xsl:value-of select="item/@name" separator=" , "/>
    <xsl:text> :: </xsl:text>
    <xsl:value-of select="item/ns:quotedString(@name)" separator=" , "/>
  </xsl:template>

  <xsl:function name="ns:quotedString">
    <xsl:param name="input"/>
    <xsl:variable name="quote">&quot;</xsl:variable>
    <xsl:value-of select="concat($quote, $input, $quote)"/>
  </xsl:function>

</xsl:stylesheet>

这给了我:

first , second , third :: "second""third""first"

请注意,如果我调用我的引用功能,则会丢失分隔符。

我使用Saxon-B 9.1.0.8进行转换。

2 个答案:

答案 0 :(得分:1)

加入一堆字符串有多种解决方案。

XPath for ... in ...

<xsl:template match="root">
    <xsl:value-of select="string-join(for $i in item return concat('&quot;', $i/@name, '&quot;'), ' , ')"/>
</xsl:template>

<string-join>加入每个item/@name的引用字符串。 <string-join>的参数是字符串。

函数调用“ns:quotedString”

<xsl:template match="root">
    <xsl:value-of select="item/ns:quotedString(@name)" separator=" , "/>
</xsl:template>

<xsl:function name="ns:quotedString">
    <xsl:param name="input"/>
    <xsl:variable name="quote">&quot;</xsl:variable>
    <xsl:sequence select="concat($quote, $input, $quote)"/>
</xsl:function>

这将回答您关于为什么不起作用的问题。请参阅函数中的<xsl:sequence>作为最后一个语句。 @separator仅在<xsl:value select="...">语句返回序列时才有效,在您的情况下,返回值是单个textnode。

答案 1 :(得分:0)

您的函数返回一个文本节点adjacent text nodes in the sequence are merged into a single text node。让它返回一个序列。

所以在您的函数中将xsl:value更改为xsl:sequence ...

<xsl:function name="ns:quotedString">
  <xsl:param name="input"/>
  <xsl:variable name="quote">&quot;</xsl:variable>
  <xsl:sequence select="concat($quote, $input, $quote)"/>
</xsl:function>

我的偏好是只将序列发送到函数...

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:ns="urn:my.name.space"
  version="2.0">

  <xsl:output method="text" media-type="text/json"/>

  <xsl:template match="root">
    <xsl:value-of select="item/@name" separator=" , "/>
    <xsl:text> :: </xsl:text>
    <xsl:value-of select="ns:quotedString(item/@name)"/>
  </xsl:template>

  <xsl:function name="ns:quotedString">
    <xsl:param name="input"/>
    <xsl:value-of select="concat('&quot;',
      string-join($input,'&quot;, &quot;'),
      '&quot;')"/>
  </xsl:function>

</xsl:stylesheet>

免责声明:我没有Saxon-B 9.1.0.8。用来测试。我使用了Saxon-HE 9.5.1.7。测试。