xslt函数用于生成基于另一个元素的属性的数字

时间:2014-05-16 15:52:01

标签: xslt

我正在尝试将一些带有奇怪格式的XML转换为html。

我有类似的东西

<spec_span span_start="c2" span_end="c9" span_name="ab12" />
...
<table_entry span_name="ab12">Text Value</entry>

我正在尝试将其转换为

<td colspan="8">Text Value</td>

大致需要做的是。

  • 使用id ab12
  • 查找span_spec
  • 从span_start和span_end
  • 中删除'c'前缀
  • 从span_end
  • 中减去span_start中剩余的整数值
  • 将1添加到最终值。

我认为应该可以为它编写某种函数。但是XSLT中的字符串操作类型转换和数学我不确定。

2 个答案:

答案 0 :(得分:1)

  

大致需要做的是。

     
      
  • 使用id ab12
  • 查找span_spec   
  • 剥离&#39; c&#39; span_start和span_end
  • 的前缀   

XSLT中的查找最好使用完成。使用 translate()函数可以轻松剥离已知字符。

将其放在样式表的顶部,在任何模板之外:

<xsl:key name="spec_span" match="spec_span" use="@span_name" />

然后将其应用于输入<table_entry>(?)元素:

<xsl:variable name="span" select="key('spec_span', @span_name)" />
<td colspan="{translate($span/@span_end, 'c', '') - translate($span/@span_start, 'c', '') + 1}">Text Value</td>

答案 1 :(得分:0)

在这种可能的解决方案中,我假设您的<spec_span><table_entry><root>元素的子项:

<root>
    <spec_span span_start="c2" span_end="c9" span_name="ab12" />
    ...
    <table_entry span_name="ab12">Text Value</table_entry>
</root>

全局选择spec_span,您可以使用此XPath 1.0表达式计算colspan

substring(//spec_span[@span_name='ab12']/@span_end, 2) -  
substring(//spec_span[@span_name='ab12']/@span_start, 2) + 1

您可以通过以下方式获取表项(全局):

//table_entry[@span_name='ab12']/text()

在XSLT中,您可以使用root上下文(或其他上下文)并调整这些表达式。这个样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="html" indent="yes"/>

    <xsl:template match="root">
        <xsl:variable name="colspan"
            select="number(substring(spec_span[@span_name='ab12']/@span_end, 2)) - number(substring(spec_span[@span_name='ab12']/@span_start, 2)) + 1"/>
        <xsl:variable name="text"
            select="table_entry[@span_name='ab12']/text()" />
        <td colspan="{$colspan}">
            <xsl:value-of select="$text"/>
        </td>
    </xsl:template>

</xsl:stylesheet>

将生成以下代码:

<td colspan="8">Text Value</td>

更好,更通用的解决方案会检查匹配的spec_spantable_entry对(具有相同的span_name,忽略不完整的对并为其他对生成代码。如果您有像这样的东西:

<root>
    <spec_span span_start="c2" span_end="c9" span_name="ab12" />
    <table_entry span_name="ab12">Text Value</table_entry>
    <spec_span span_start="c2" span_end="c12" span_name="ab17" />
    <spec_span span_start="c2" span_end="c12" span_name="ab15" />
    <table_entry span_name="ab15">Text Value 2</table_entry>
    <table_entry span_name="ab16">Text Value 3</table_entry>
</root>

您可以使用此样式表(也适用于XSLT 2.0):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="html" indent="yes"/>

    <xsl:template match="root">
        <xsl:apply-templates select="spec_span[//table_entry/@span_name = @span_name]"/>
    </xsl:template>

    <xsl:template match="spec_span">
        <xsl:variable name="span_name" select="@span_name"/>
        <xsl:variable name="colspan"
            select="number(substring(@span_end, 2)) - number(substring(@span_start, 2)) + 1"/>
        <td colspan="{$colspan}">
            <xsl:value-of select="//table_entry[@span_name=$span_name]"/>
        </td>
    </xsl:template>

</xsl:stylesheet>

将处理任何spec_span / table_entry对(包括您发布的示例)。对于上面的示例,它将生成两个td,因为只有两对匹配:

<td colspan="8">Text Value</td>
<td colspan="11">Text Value 2</td>