我在使用XSLT生成的表时遇到了困难。
我的XML是一个食谱。任何粗体的行都将格式化为表格。我的问题是表格在输出上重复。我尝试了各种分组方案,但没有任何运气解决方案。有没有人能够洞察我所缺少的东西?感谢。
XML:
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Ingredients</p>
<p><b>1 cup of flour</b></p>
<p><b>2 eggs</b></p>
<p><b>1/4 stick of butter</b></p>
<p><b>1/4 cup of sugar</b></p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
守则:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*/p/b" >
<table>
<xsl:apply-templates select="//b" mode="test"/>
</table>
</xsl:template>
<xsl:template match="//b" mode="test">
<tr>
<td>
<xsl:value-of select="substring-before(., ' ')" />
</td>
<td>
<xsl:value-of select="substring-after(., ' ')" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
输出:
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Ingredients</p>
<p><table><tr><td>1</td><td>cup of flour</td></tr>
<tr><td>2</td><td>eggs</td></tr>
<tr><td>1/4</td><td>stick of butter</td></tr>
<tr><td>1/4</td><td>cup of sugar</td></tr>
</table></p>
<p><table><tr><td>1</td><td>cup of flour</td></tr>
<tr><td>2</td><td>eggs</td></tr>
<tr><td>1/4</td><td>stick of butter</td></tr>
<tr><td>1/4</td><td>cup of sugar</td></tr>
</table></p>
<p><table><tr><td>1</td><td>cup of flour</td></tr>
<tr><td>2</td><td>eggs</td></tr>
<tr><td>1/4</td><td>stick of butter</td></tr>
<tr><td>1/4</td><td>cup of sugar</td></tr>
</table></p>
<p><table><tr><td>1</td><td>cup of flour</td></tr>
<tr><td>2</td><td>eggs</td></tr>
<tr><td>1/4</td><td>stick of butter</td></tr>
<tr><td>1/4</td><td>cup of sugar</td></tr>
</table></p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
答案 0 :(得分:2)
这个简单的转换(没有xsl:if
,没有count()
,没有preceding-sibling::
轴)只是对提供的代码的轻微修改:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="p[b][1]/b" >
<table>
<xsl:apply-templates select="//b" mode="test"/>
</table>
</xsl:template>
<xsl:template match="//b" mode="test">
<tr>
<td>
<xsl:value-of select="substring-before(., ' ')" />
</td>
<td>
<xsl:value-of select="substring-after(., ' ')" />
</td>
</tr>
</xsl:template>
<xsl:template match="p[b][position() > 1]"/>
</xsl:stylesheet>
应用于提供的XML文档:
<t>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Ingredients</p>
<p><b>1 cup of flour</b></p>
<p><b>2 eggs</b></p>
<p><b>1/4 stick of butter</b></p>
<p><b>1/4 cup of sugar</b></p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
</t>
产生想要的结果:
<t>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Ingredients</p>
<p>
<table>
<tr>
<td>1</td>
<td>cup of flour</td>
</tr>
<tr>
<td>2</td>
<td>eggs</td>
</tr>
<tr>
<td>1/4</td>
<td>stick of butter</td>
</tr>
<tr>
<td>1/4</td>
<td>cup of sugar</td>
</tr>
</table>
</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
</t>
答案 1 :(得分:1)
你快到了!
您的问题在于如何处理b [旧]节点。通过使用// b,您实际上是沿着错误的轴选择,因此您将获取所有4个b节点(因此重复)。
以下转换在我的机器上输出以下结果:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*/p[b]" >
<xsl:if test="count(preceding-sibling::p[b]) = 0">
<table>
<xsl:apply-templates select="parent::node()//b" mode="test"/>
</table>
</xsl:if>
</xsl:template>
<xsl:template match="b" mode="test">
<tr>
<td>
<xsl:value-of select="substring-before(., ' ')" />
</td>
<td>
<xsl:value-of select="substring-after(., ' ')" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
结果:
<Recipe>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Ingredients</p>
<table>
<tr>
<td>1</td>
<td>cup of flour</td>
</tr>
<tr>
<td>2</td>
<td>eggs</td>
</tr>
<tr>
<td>1/4</td>
<td>stick of butter</td>
</tr>
<tr>
<td>1/4</td>
<td>cup of sugar</td>
</tr>
</table>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
</Recipe>
(注意我将原始XML片段与节点一起用来创建格式良好的文档)
这是如何工作的?好吧,诀窍在于我们匹配p / b模式多少次 - 虽然它存在四次,但我们只想要一个包含所有后续b节点作为子节点的表。
因此,我们通过计算此模式之前发生的次数来测试第一个带有子b p[b]
的p - count(preceding-sibling::p[b]) = 0
给出了第一个p。{{1}}。然后我们爬回一个节点并从这里选择所有b个孩子。