XSLT动态标记插入,用于项目符号点元素

时间:2018-10-26 05:26:10

标签: xml xslt

我才刚刚开始了解XSLT,并查看W3school示例以解决雇主给我的新任务。

我有一些文件需要按照以下XML结构进行转换。

     <tablecell bgcolor='white'>
<pardef id='16' leftmargin='0.2757in' list='bullet' keepwithnext='true' keeptogether='true'/>
        <par def='34'>
            <run>
                <font size='8pt' name='Verdana' pitch='variable' truetype='true'
     familyid='20' color='navy'/>Data in bullet point 1</run>
        </par>
        <par def='34'>
            <run>
                <font size='8pt' name='Verdana' pitch='variable' truetype='true'
     familyid='20' color='navy'/>Data in bullet point 2</run>
        </par>
        <par def='34'>
            <run>
                <font size='8pt' name='Verdana' pitch='variable' truetype='true'
     familyid='20' color='navy'/>Data in bullet point 3</run>
        </par>
        <par def='34'>
            <run>
                <font size='8pt' name='Verdana' pitch='variable' truetype='true'
     familyid='20' color='navy'/>Data in bullet point 4</run>
        </par>
    </tablecell>

到目前为止,我的XSL可以处理xml的内容如下。

    <xsl:template match="tablecell">
            <td>
                <xsl:copy-of select="@colspan" />
                <!--<xsl:value-of select="."/> -->
                <xsl:apply-templates select="table" />
                <xsl:apply-templates select="section" />
                <xsl:apply-templates select="par" />
                <xsl:apply-templates select="pardef" />
            </td>
    </xsl:template>

<xsl:template match="pardef">
        <xsl:if test="@list='bullet'">
            <ul>
                <xsl:apply-templates/>
         </xsl:if>
    </xsl:template>

    <xsl:template match="par">
            <p>
                <xsl:apply-templates select="run" />
            </p>
    </xsl:template>

    <xsl:template match="run">
            <li>
                <xsl:apply-templates select="run" />
            </li>
    </xsl:template>

我遇到的问题是,我不确定在最后一个</ul>元素后动态插入结束<run>标记以创建项目符号点的最佳方法。实际上,我的XML文件中可以有任意数量的<run>标签要转换。

这是我需要对变量进行处理并计算元素数量,然后基于此变量进行一些处理的地方吗?

我需要满足的另一种情况是<run>标签仅在<li>标签包围下,如果它们在pardef / par结构下,其中pardef元素具有属性列表=“子弹”。

这是我要实现的输出。

<p>
    <ul>
        <li>Data in bullet point 1</li>
        <li>Data in bullet point 2</li>
        <li>Data in bullet point 3</li>
        <li>Data in bullet point 4</li>
    </ul>  
</p>

如果您能为我正确指出上述两个查询的正确方向,

欢呼


除了编辑现有线程外,不确定如何使用更多代码段继续该现有线程。如果您能让我知道该怎么做,那就太好了。

感谢到目前为止所有已帮助解决此问题的人。以前有人对此帖子做出了响应,提出了使用模式的想法,这有助于我进一步发展。 我现在遇到的问题是以下情况,如果遇到<par>标签,属性def = 16,我希望它使用mode ='sixteen'模板,否则使用通用基本面值模板,该模板仅使用{ {1}} <p>标签。 如何做到这一点?现在,我正在考虑使用if语句,但这将是最佳做法吗?

此外,以下代码是否意味着</p>元素可能被处理了两次?

<par>

这是我的尝试,不确定是否正确或最佳做法。

<xsl:template match="tablecell">
        <td>
            <!-- <xsl:copy-of select="@colspan" /> -->
            <xsl:apply-templates select="par" />
            <xsl:apply-templates select="table" />
            <xsl:apply-templates select="section" />

            <!-- Apply to par elements where attribute def=16 -->   
            <xsl:apply-templates select="par[@def='16']" mode='sixteen' />
        </td>
    </xsl:template>

    <!-- Template for par elements where attribute def=16 -->
    <xsl:template match="par" mode='sixteen'>
        <ul>
            <!-- Apply to any table elements -->    
            <xsl:apply-templates select="run" mode='bullet' />
        </ul>
    </xsl:template>

1 个答案:

答案 0 :(得分:0)

您缺少的关键点是XSLT不会在输出中创建开始和结束标签,而是创建节点树。您不能将半个节点写入树。像<ul> XXX </ul>这样的“文字结果元素”是一条指令,它(a)评估XXX以创建某些内容,并且(b)创建该内容所附加到的UL元素节点。您必须将<ul></ul>视为构建节点的一条指令,而不是先创建开始标记的指令,再创建结束标记的指令。

您的问题是经典的位置分组问题。实际上,它是XSLT规范中xsl:for-each-group指令中使用的示例之一:在https://www.w3.org/TR/xslt-30/#element-for-each-group中搜索“示例:分组元素的交替序列”。请注意,此指令需要XSLT 2.0或XSLT 3.0。在许多环境中,默认的XSLT处理器仍然仅支持XSLT 1.0。在1.0中解决这个问题要困难得多(这并非不可能,但这对于新手来说是一个巨大的挑战)。因此,请确保您使用的处理器支持2.0或3.0。