如何使用XSLT递归删除一些xml元素
所以我的处境很糟糕。我有一个这样的XML如何使用XSLT递归删除一些xml元素,xml,xslt,recursion,Xml,Xslt,Recursion,所以我的处境很糟糕。我有一个这样的XML <table border="1" cols="200 100pt 200"> <tr> <td>isbn</td> <td>title</td> <td>price</td> </tr> <tr> <td /> <td /&
<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>
isbn
标题
价格
[名称]
[名称]
菲勒
福
酒吧
喝倒采
福
喝倒采
酒吧
福
喝倒采
福
喝倒采
福
喝倒采
现在的问题是如何递归删除所有空的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”的表元素
isbn
标题
价格
[名称]
[名称]
菲勒
福
酒吧
喝倒采
福
喝倒采
酒吧
福
喝倒采
福
喝倒采
福
喝倒采
您将如何解决此问题?您还可以使用类似的方法(未测试)筛选出任何只包含with empty的表和任何只包含with empty的表(除了其他筛选器之外):
听起来您对空的定义是“不包含文本或仅包含空白”。是这样吗?如果是这样的话,下面的转换应该可以做到这一点:
<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>
这是您的解决方案:
<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>
这是因为
包含空元素
和其他元素的情况。然后你想删除
s,只剩下剩下剩下的部分。+1这既干净又实用。请注意,normalizespace(.)
相当于normalize-space()
好问题!无论如何,删除所有空的
节点可能有点过头了-它们是保持合理的表结构所必需的。谢谢,足够好了,唯一要添加的是在验证节点数时使用msxls:node set($content)。我在XMLSpy中对其进行了测试,count($content/node())工作正常。
<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>
<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>
<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>
<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>