[英]How to remove the first child of an XML node with XSL?
Data.xls
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="Data" select="document('Data.xml')/*[1]"/>
<xsl:template match="/">
<xsl:call-template name="remove-first-child">
<xsl:with-param name="Node" select="$Data"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="remove-first-child">
<xsl:param name="Node"/>
<xsl:element name="{name($Node)}">
<xsl:copy-of select="$Node/@* | $Node/*[position() > 1]"/>
</xsl:element>
</xsl:template>
<!-- same as above, but for testing over 2 recursion levels -->
<xsl:template name="remove-first-child1">
<xsl:param name="Node"/>
<xsl:call-template name="remove-first-child">
<xsl:with-param name="Node">
<xsl:element name="{name($Node)}">
<xsl:copy-of select="$Node/@* | $Node/*[position() > 1]"/>
</xsl:element>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
如何删除数据中的第一个孩子并产生可以再次传递给remove-first-child的输出?
调用第一个模板时,我得到:
$> msxsl Other.xml Data.xsl
<Alphabet>
<B/>
<C/>
...
</Alphabet>
当我更改为调用第二个模板时,我得到:
$> msxsl Other.xml Data.xsl
Error occured while executing stylesheet 'Data.xsl'.
Code: 0x80004005
Reference to variable or parameter 'Node' must evaluate to a node list.
理想的结果将是:
<Alphabet>
<C/>
...
</Alphabet>
更新:我如何尝试应用建议的解决方案。
<xsl:template match="node()|@*" mode="remove-first-child">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="remove-first-child"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()[parent::*][not(preceding-sibling::*)]" mode="remove-first-child"/>
<xsl:template name="remove-first-child-a">
<xsl:param name="Node"/>
<xsl:apply-templates select="$Node" mode="remove-first-child"/>
</xsl:template>
<xsl:template name="remove-first-child-b">
<xsl:param name="Node"/>
<xsl:variable name="Temp">
<xsl:apply-templates select="$Node" mode="remove-first-child"/>
</xsl:variable>
<xsl:apply-templates select="$Temp" mode="remove-first-child"/>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="remove-first-child-a">
<!-- xsl:call-template name="remove-first-child-b" -->
<xsl:with-param name="Node" select="$Data"/>
</xsl:call-template>
</xsl:template>
但这也只会产生与上述相同的结果。 a
:
$> msxsl Other.xml Data.xsl
<Alphabet>
<B/>
<C/>
...
</Alphabet>
b
:
$> msxsl Other.xml Data.xsl
Error occured while executing stylesheet 'Data.xsl'.
Code: 0x80004005
Expression must evaluate to a node-set.
-->$Temp<--
所以我想关键是类型系统...
并且要注意:主要操作发生在Other.xml
,这不仅仅是一个虚拟调用。 一些数据是从Data.xml
的,在与Other.xsl
之前将要进行处理。 该处理仅包括删除依赖于某些条件(不是此问题的一部分)的第一个子对象,这些条件恰好是递归实现的,因为它是XSL。 并且在递归过程中,可能有必要删除相同和不同的遍历节点的多个第一个子级。
我想在XSL中表示的是投影node --> node
,删除输入节点的第一个子节点。
对于XSLT中的这种递归(即,遵循输入文档的结构),您要使用apply-templates
而不是call-template
。 这避免了您遇到的问题(缺少节点集),因为该模板将仅应用于存在的节点。
以下转换设置了一个标准的身份模板,然后添加了对第一个子对象不产生任何影响的替代。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Standard identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- Skip first child -->
<!-- the "parent" check is needed so that the root node is not skipped -->
<xsl:template match="node()[parent::*][not(preceding-sibling::*)]" />
<xsl:variable name="data-doc" select="document('Data.xml')"/>
<xsl:template match="/">
<xsl:apply-templates select="$data-doc/*" />
</xsl:template>
</xsl:stylesheet>
应用于虚拟文档,其中外部文件Data.xml
包含以下示例输入,
<A>
<B1>
<C1 />
<C2 />
</B1>
<B2>
<C1 />
<C2 />
</B2>
<B3>
<C1 />
<C2>
<D1 />
<D2 />
</C2>
<C3>
<D1 />
</C3>
</B3>
</A>
结果如下:
<?xml version="1.0" encoding="utf-8"?>
<A>
<B2>
<C2 />
</B2>
<B3>
<C2>
<D2 />
</C2>
<C3>
</C3>
</B3>
</A>
您可以使用 :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*//*[position()<=1]"/>
</xsl:stylesheet>
如果要同时过滤第一个和第二个元素,则将“ 1”乘“ 2”(按harpo的答案中的说明工作)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.