循环遍历XSLT中的分隔字符列表

时间:2015-01-09 19:36:07

标签: xml 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 M  
ENC1101 111222 M  
ENC1101 111222 W  
ENC1101 111222 F  

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

有各种各样的日组合 - 我需要每天特定参考符合一行。

感谢任何帮助。谢谢!

3 个答案:

答案 0 :(得分:2)

首先,您必须为输入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
根据要求

答案 1 :(得分:0)

对于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>

要求在文档中包含顶级节点。

答案 2 :(得分:0)

对于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