0

我试图找出使用 XSL 遍历空格分隔列表的元素的最简单方法。假设我们有以下 XML 数据文件:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <!-- this list has 6 items -->
    <list>this is a list of strings</list>
</data>

列表元素可以像这样在 XML Schema 中定义:

<xs:element name="list" type="strlist" />

<xs:simpleType name="strlist">
    <xs:list itemType="xs:string" />
</xs:simpleType>

我不确定 XSL 规范是否直接支持这种结构,但我认为它应该支持,因为它可以在 XML Schema 中使用。

任何帮助将不胜感激。

4

2 回答 2

1

XML Schema 早于 XSLT 2.0,因此 XSLT 2.0 可以通过tokenize().

XSLT 1.0 早于 XML Schema,因此您需要一个递归模板调用来分割字符串:

T:\ftemp>type tokenize.xml
<?xml version="1.0" encoding="UTF-8"?>
<data>
    <!-- this list has 6 items -->
    <list>this is a list of strings</list>
</data>
T:\ftemp>xslt tokenize.xml tokenize.xsl
this,is,a,list,of,strings
T:\ftemp>type tokenize.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

<xsl:output method="text"/>

<xsl:template match="data">
  <xsl:call-template name="tokenize">
    <xsl:with-param name="string" select="normalize-space(list)"/>
  </xsl:call-template>
</xsl:template>

<xsl:template name="tokenize">
  <xsl:param name="string"/>
  <xsl:choose>
    <xsl:when test="contains($string,' ')">
      <xsl:value-of select="substring-before($string,' ')"/>
      <xsl:text>,</xsl:text>
      <xsl:call-template name="tokenize">
        <xsl:with-param name="string" select="substring-after($string,' ')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>
T:\ftemp>xslt2 tokenize.xml tokenize2.xsl
this,is,a,list,of,strings
T:\ftemp>type tokenize2.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">

<xsl:output method="text"/>

<xsl:template match="data">
  <xsl:value-of select="tokenize(list,'\s+')" separator=","/>
</xsl:template>

</xsl:stylesheet>
T:\ftemp>
于 2013-07-30T01:50:27.250 回答
1

XSLT 2.0 直接支持这一点:在模式感知转换中,您可以编写

<xsl:for-each select="data(list)">
  ...
</xsl:for-each>

如果元素“list”在模式中定义为列表类型,这将遍历标记。

但是你也可以通过编写没有模式来做到这一点

<xsl:for-each select="tokenize(list, '\s+')">...</xsl:for-each>

在 XSLT 1.0 中,您需要使用递归命名模板;您可以在 www.exslt.org 找到现成的 str:tokenize 模板以复制到您的样式表中。

于 2013-07-30T06:49:22.543 回答