遍历 XSLT 中分隔的字符列表

Looping over a delimited list of characters in XSLT

所以我的 XML 如下:

<Classes>  
  <Classes_Per_Term>  
    <Course>ENC1101</Course>
    <Ref_Code>111111</Ref_Code>
    <Days_of_Week>M</Days_of_Week>
  </Classes_Per_Term>
  <Classes_Per_Term>  
    <Course>ENC1101</Course>
    <Ref_Code>111222</Ref_Code>
    <Days_of_Week>M W F</Days_of_Week>
  </Classes_Per_Term>  
</Classes>

我需要这样的输出

ENC1101 111111 米
ENC1101 111222 米
ENC1101 111222 W
ENC1101 111222 楼

我正在使用 <xsl:value-of> 调用打印 <Course><Ref_Code>,并使用换行符跳到下一行。我不确定如何在 <Days_of_Week> 节点内设置循环。

有各种各样的日期组合 - 我需要为特定参考满足的每一天排一行。

感谢任何帮助。谢谢!

首先,您的输入必须有一个根元素 XML,否则它的格式不正确:

<?xml version="1.0" encoding="UTF-8"?>
<Classes>
  <Classes_Per_Term>  
    <Course>ENC1101</Course>
    <Ref_Code>111111</Ref_Code>
    <Days_of_Week>M</Days_of_Week>
  </Classes_Per_Term>
  <Classes_Per_Term>  
    <Course>ENC1101</Course>
    <Ref_Code>111222</Ref_Code>
    <Days_of_Week>M W F</Days_of_Week>
  </Classes_Per_Term>  
</Classes>

XSLT 2.0 解决方案

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/Classes/Classes_Per_Term">
    <xsl:variable name="course" select="Course"/>
    <xsl:variable name="refcode" select="Ref_Code"/>
    <xsl:for-each select="tokenize(Days_of_Week, ' ')">
      <xsl:value-of select="concat($course, ' ', $refcode, ' ', ., '&#xa;')"/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

产量

ENC1101 111111 M
ENC1101 111222 M
ENC1101 111222 W
ENC1101 111222 F

根据要求。

对于 XSLT 1.0 解决方案,有必要生成一个没有 tokenize() 的序列。该解决方案不使用递归,而是使用文档的节点作为生成器来提供位置值和字符串长度过滤器。

该解决方案对于一周中不同长度的日子或令牌数量可能超过文档中节点总数的应用程序不稳健。在这种情况下,递归结构中更全面的解析器可能更合适。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" indent="no" />
    <xsl:template match="Classes_Per_Term">
    <xsl:variable name="Classes" select="." />
        <xsl:variable name="Days" select="Days_of_Week" />
        <xsl:for-each select="//*">
            <xsl:variable name="Day" select="substring($Classes/Days_of_Week, position() * 2 - 1, 1)" />
            <xsl:if test="position() &lt;= (string-length($Days) + 1) div 2">
                <xsl:value-of select="$Classes/Course" />
                <xsl:text> </xsl:text>
                <xsl:value-of select="$Classes/Ref_Code" />
                <xsl:text> </xsl:text>
                <xsl:value-of select="$Day" />
                <xsl:text>
</xsl:text>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

在文档中保留顶级节点的要求仍然存在。

对于 XSLT 1.0,这几乎可以通过递归轻松解决。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" />
  <xsl:strip-space elements="*" />

  <xsl:template match="Classes_Per_Term">
    <xsl:param name="days" select="Days_of_Week" />
    <xsl:variable name="day" select="substring-before(concat($days, ' '), ' ')" />
    <xsl:if test="$day">
      <xsl:value-of select="concat(Course, ' ', Ref_Code, ' ', $day, '&#xA;')" />
      <xsl:apply-templates select=".">
        <xsl:with-param name="days" select="substring-after($days, ' ')" />
      </xsl:apply-templates>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

按需输出

ENC1101 111111 M
ENC1101 111222 M
ENC1101 111222 W
ENC1101 111222 F

此模板不断调用自身,直到用完 $days,每次调用打印一个 $day

http://xsltransform.net/6qVRKw4