[英]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.