所以我觉得这种情况很糟糕。我有这样的XML
<table border="1" cols="200 100pt 200">
<tr>
<td>isbn</td>
<td>title</td>
<td>price</td>
</tr>
<tr>
<td />
<td />
<td>
<span type="champsimple" id="9b297fb5-d12b-46b1-8899-487a2df0104e" categorieid="a1c70692-0427-425b-983c-1a08b6585364" champcoderef="01f12b93-b4c5-401b-9da1-c9385d77e43f">
[prénom]
</span>
<span type="champsimple" id="e103a6a5-d1be-4c34-8a54-d234179fb4ea" categorieid="a1c70692-0427-425b-983c-1a08b6585364" champcoderef="01f12b93-b4c5-401b-9da1-c9385d77e43f">[nom]</span>
<span></span>
</td>
</tr>
<tr></tr>
<tr>
<td></td>
<td>Phill It in</td>
</tr>
<tr>
<table id="cas1">
<tr>
<td ></td>
<td >foo</td>
</tr>
<tr>
<td >bar</td>
<td >boo</td>
</tr>
</table>
</tr>
<tr>
<table id="cas2">
<tr>
<td ></td>
<td >foo</td>
</tr>
<tr>
<td ></td>
<td >boo</td>
</tr>
</table>
</tr>
<tr>
<table id="cas3">
<tr>
<td >bar</td>
<td ></td>
</tr>
<tr>
<td >foo</td>
<td >boo</td>
</tr>
</table>
</tr>
<tr>
<table id="cas4">
<tr>
<td />
<td />
</tr>
<tr>
<td>foo</td>
<td>boo</td>
</tr>
</table>
</tr>
<table id="cas4">
<tr>
<td />
<td />
</tr>
<tr>
<td>foo</td>
<td>boo</td>
</tr>
</table>
<tr>
<td />
<td />
</tr>
</table>
现在问题是如何递归删除所有空的td,tr和table元素?
现在我使用这个XSLT
<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="td[not(node())]" />
<xsl:template match="tr[not(node())]" />
<xsl:template match="table[not(node())]" />
</xsl:stylesheet>
但它做得并不好。删除td后,tr变为空,但不处理。太糟糕了。请使用“cas4”查看表格元素。
<table border="1" cols="200 100pt 200">
<tr>
<td>isbn</td>
<td>title</td>
<td>price</td>
</tr>
<tr>
<td>
<span type="champsimple" id="9b297fb5-d12b-46b1-8899-487a2df0104e" categorieid="a1c70692-0427-425b-983c-1a08b6585364" champcoderef="01f12b93-b4c5-401b-9da1-c9385d77e43f">
[prénom]
</span>
<span type="champsimple" id="e103a6a5-d1be-4c34-8a54-d234179fb4ea" categorieid="a1c70692-0427-425b-983c-1a08b6585364" champcoderef="01f12b93-b4c5-401b-9da1-c9385d77e43f">[nom]</span>
<span />
</td>
</tr>
<tr>
<td>Phill It in</td>
</tr>
<tr>
<table id="cas1">
<tr>
<td>foo</td>
</tr>
<tr>
<td>bar</td>
<td>boo</td>
</tr>
</table>
</tr>
<tr>
<table id="cas2">
<tr>
<td>foo</td>
</tr>
<tr>
<td>boo</td>
</tr>
</table>
</tr>
<tr>
<table id="cas3">
<tr>
<td>bar</td>
</tr>
<tr>
<td>foo</td>
<td>boo</td>
</tr>
</table>
</tr>
<tr>
<table id="cas4">
<tr />
<tr>
<td>foo</td>
<td>boo</td>
</tr>
</table>
</tr>
<table id="cas4">
<tr />
<tr>
<td>foo</td>
<td>boo</td>
</tr>
</table>
<tr />
</table>
答案 0 :(得分:4)
听起来你的空的定义是“不包含文本或只包含空白”。是这样的吗?如果是这样,以下转换应该可以解决问题:
<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="td[not(normalize-space(.))]" />
<xsl:template match="tr[not(normalize-space(.))]" />
<xsl:template match="table[not(normalize-space(.))]" />
</xsl:stylesheet>
答案 1 :(得分:1)
您还可以过滤掉任何仅包含&lt; tr&gt;的表格。空的&lt; td&gt;,以及任何&lt; tr&gt;只有空&lt; tr&gt; (除了你的其他过滤器),使用这样的东西(未测试):
<xsl:template match="tr[not(td/node())]" />
<xsl:template match="table[not(tr/td/node())]" />
答案 2 :(得分:1)
有你的解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="@* | text()">
<xsl:copy />
</xsl:template>
<xsl:template match="table | tr | td">
<!-- result of the transformation of descendants -->
<xsl:variable name="content">
<xsl:apply-templates select="node()" />
</xsl:variable>
<!-- if there are any children left then copy myself -->
<xsl:if test="count($content/node()) > 0">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:copy-of select="$content" />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
这个想法很简单。我会先为我的后代进行改造,然后我会看看是否还有人离开。如果是这样,我会复制自己和转化的结果。
如果要保留表结构并仅删除空行 - 仅包含空元素<tr>
的元素<td>
,而不仅仅为<tr>
创建具有不同条件的类似模板并忽略元素<td>
。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="@* | text()">
<xsl:copy />
</xsl:template>
<xsl:template match="table">
<!-- result of the transformation of descendants -->
<xsl:variable name="content">
<xsl:apply-templates select="node()" />
</xsl:variable>
<!-- if there are any children left then copy myself -->
<xsl:if test="count($content/node()) > 0">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:copy-of select="$content" />
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="tr">
<!-- result of the transformation of descendants -->
<xsl:variable name="content">
<xsl:apply-templates select="node()" />
</xsl:variable>
<!-- number of non-empty td elements -->
<xsl:variable name="cellCount">
<xsl:value-of select="count($content/td[node()])" />
</xsl:variable>
<!-- number of other elements -->
<xsl:variable name="elementCount">
<xsl:value-of select="count($content/node()[name() != 'td'])" />
</xsl:variable>
<xsl:if test="$cellCount > 0 or $elementCount > 0">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:copy-of select="$content" />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
嗯,实际上最后一个if
应该是这样的:
<xsl:choose>
<!-- if there are cells then copy the content -->
<xsl:when test="$cellCount > 0">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:copy-of select="$content" />
</xsl:copy>
</xsl:when>
<!-- if there are only other elements copy them -->
<xsl:when test="$elementCount > 0">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:copy-of select="$content/node()[name() != 'td']" />
</xsl:copy>
</xsl:when>
</xsl:choose>
这是因为<tr>
包含空元素<td>
和其他元素的情况。然后,您要删除<td>
并仅保留其余内容。