我才刚刚开始了解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>
答案 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。