[英]XSLT Create copies of Parent Node from Child Nodes
I'm working with XSLT and I have a requirement that I'm not sure how to proceed with. 我正在使用XSLT,并且有一个我不确定如何继续的要求。
I've included images below as the scenario is a bit difficult to explain. 由于场景很难解释,因此我在下面提供了图像。
Before : There is 1 tree node and there are 2 leaf nodes in each of the nodes. 之前 :有1个树节点,每个节点中有2个叶节点。
After : There are 2 tree nodes. 之后 :有2个树节点。 The 1st tree holds the first leaf nodes under leaves and the 2nd tree holds the second leaf nodes under leaves. 第一棵树在叶子下保存第一个叶子节点,第二棵树在叶子下保存第二个叶子节点。
I'm unsure if I should go outwards in, tree -> leaf or inwards out, leaf -> tree in my template matching.. 我不确定是否应该在模板匹配中从树->叶子向内走,或从树->树向内走。
Thank you for any help! 感谢您的任何帮助!
Update: 更新:
Before XML as Text 在XML作为文本之前
<?xml version="1.0" encoding="UTF-8"?>
<tree uId="0">
<branches uId="1">
<branch uId="2">
<branchId uId="3">0988890098887656</branchId>
<number uId="4">7</number>
<leaves uId="5">
<leaf uId="6">
<name uId="7">Leaf 1</name>
</leaf>
<leaf uId="8">
<name uId="9">Leaf 2</name>
</leaf>
</leaves>
<bugs uId="10">10</bugs>
</branch>
<branch uId="11">
<branchId uId="12">66677755564446</branchId>
<number uId="13" />
<leaves uId="14">
<leaf uId="15">
<name uId="16">Leaf 1</name>
</leaf>
<leaf uId="17">
<name uId="18">Leaf 2</name>
</leaf>
</leaves>
<bugs uId="19" />
</branch>
</branches>
<title uId="20">Great Tree</title>
</tree>
After XML as Text: 在XML作为文本之后:
<tree uId="0">
<branches uId="1">
<branch uId="2">
<branchId uId="3">0988890098887656</branchId>
<number uId="4">7</number>
<leaves uId="5">
<leaf uId="6">
<name uId="7">Leaf 1</name>
</leaf>
</leaves>
<bugs uId="10">10</bugs>
</branch>
<branch uId="11">
<branchId uId="12">66677755564446</branchId>
<number uId="13" />
<leaves uId="14">
<leaf uId="15">
<name uId="16">Leaf 1</name>
</leaf>
</leaves>
<bugs uId="19" />
</branch>
</branches>
<title uId="20">Great Tree</title>
</tree>
<tree>
<branches>
<branch>
<branchId>0988890098887656</branchId>
<number>7</number>
<leaves>
<leaf uId="8">
<name uId="9">Leaf 2</name>
</leaf>
</leaves>
<bugs>10</bugs>
</branch>
<branch>
<branchId>66677755564446</branchId>
<number/>
<leaves>
<leaf uId="17">
<name uId="18">Leaf 2</name>
</leaf>
</leaves>
<bugs />
</branch>
</branches>
<title>Great Tree</title>
</tree>
XSLT: XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="xs"
version="1.0">
<xsl:template match="tree">
<xsl:variable name="copies">
<xsl:call-template name="getTreeCopies" />
</xsl:variable>
<xsl:copy-of select="exsl:node-set($copies)/*"/>
</xsl:template>
<xsl:template name="getTreeCopies">
<xsl:variable name="countOfLeaf" select="count((.//leaves)[1]/leaf)" />
<xsl:call-template name="getTreeCopy">
<xsl:with-param name="i">1</xsl:with-param>
<xsl:with-param name="count">
<xsl:value-of select="$countOfLeaf" />
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="getTreeCopy">
<xsl:param name="i" />
<xsl:param name="count" />
<xsl:if test="$i <= $count">
<xsl:copy-of select="."/>
<xsl:call-template name="getTreeCopy" >
<xsl:with-param name="i">
<xsl:value-of select="$i + 1"/>
</xsl:with-param>
<xsl:with-param name="count">
<xsl:value-of select="$count"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
My XSLT so far copies the tree node (number of leaf nodes in leaves node per branch) times. 到目前为止,我的XSLT复制树节点(每个分支的叶子节点中的叶子节点数)倍。 The next step would be to remove leaf at position 1 from tree 1 and leaf at position 2 from tree 2... etc and then remove the uid attributes from any copies of the original tree. 下一步是从树1删除位置1的叶子,从树2删除位置2的叶子...等等,然后从原始树的任何副本中删除uid属性。
An alternative way would be to: 另一种方法是:
leaf
's based on their position. 根据leaf
的位置创建一个键。 leaf
for each key. 处理每个密钥的第一leaf
。 ( Muenchian Grouping ) ( Muenchian分组 ) leaf
's in the key are passed as a parameter. 密钥中所有leaf
的生成ID的列表作为参数传递。 (Since XSLT 1.0 doesn't support tunneling, it will need to be passed in each apply-templates call.) (由于XSLT 1.0不支持隧道,因此需要在每个apply-templates调用中传递它。) leaves
element is processed, only leaf
elements with a matching generated ID are processed. 处理leaves
元素时,仅处理具有匹配的生成ID的leaf
元素。 mode
's can control whether or not attributes are processed. 使用mode
可以控制是否处理属性。 Example (also demonstrated here: http://xsltfiddle.liberty-development.net/6qM2e2a )... 示例(也在此处演示: http : //xsltfiddle.liberty-development.net/6qM2e2a )...
XML Input XML输入
<tree uId="0">
<branches uId="1">
<branch uId="2">
<branchId uId="3">0988890098887656</branchId>
<number uId="4">7</number>
<leaves uId="5">
<leaf uId="6">
<name uId="7">Leaf 1</name>
</leaf>
<leaf uId="8">
<name uId="9">Leaf 2</name>
</leaf>
</leaves>
<bugs uId="10">10</bugs>
</branch>
<branch uId="11">
<branchId uId="12">66677755564446</branchId>
<number uId="13" />
<leaves uId="14">
<leaf uId="15">
<name uId="16">Leaf 1</name>
</leaf>
<leaf uId="17">
<name uId="18">Leaf 2</name>
</leaf>
</leaves>
<bugs uId="19" />
</branch>
</branches>
<title uId="20">Great Tree</title>
</tree>
XSLT 1.0 XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="leaves" match="leaf" use="count(preceding-sibling::leaf) + 1"/>
<xsl:template match="/">
<xsl:apply-templates select="//leaf[count(.|key('leaves',count(preceding-sibling::leaf) + 1)[1])=1]"/>
</xsl:template>
<xsl:template match="@*|node()" mode="full">
<xsl:param name="leafId"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="full">
<xsl:with-param name="leafId" select="$leafId"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()" mode="partial">
<xsl:param name="leafId"/>
<xsl:copy>
<xsl:apply-templates select="node()" mode="partial">
<xsl:with-param name="leafId" select="$leafId"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="leaves" mode="full">
<xsl:param name="leafId"/>
<xsl:copy>
<xsl:apply-templates select="@*|leaf[contains($leafId,concat('|',generate-id()))]" mode="full"/>
</xsl:copy>
</xsl:template>
<xsl:template match="leaves" mode="partial">
<xsl:param name="leafId"/>
<xsl:copy>
<xsl:apply-templates select="leaf[contains($leafId,concat('|',generate-id()))]" mode="full"/>
</xsl:copy>
</xsl:template>
<xsl:template match="leaf">
<xsl:variable name="leafId">
<xsl:for-each select="key('leaves',count(preceding-sibling::leaf)+1)">
<xsl:value-of select="concat('|',generate-id())"/>
</xsl:for-each>
</xsl:variable>
<xsl:choose>
<xsl:when test="position() = 1">
<xsl:apply-templates select="ancestor::tree" mode="full">
<xsl:with-param name="leafId" select="$leafId"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="ancestor::tree" mode="partial">
<xsl:with-param name="leafId" select="$leafId"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Output 输出量
<tree uId="0">
<branches uId="1">
<branch uId="2">
<branchId uId="3">0988890098887656</branchId>
<number uId="4">7</number>
<leaves uId="5">
<leaf uId="6">
<name uId="7">Leaf 1</name>
</leaf>
</leaves>
<bugs uId="10">10</bugs>
</branch>
<branch uId="11">
<branchId uId="12">66677755564446</branchId>
<number uId="13"/>
<leaves uId="14">
<leaf uId="15">
<name uId="16">Leaf 1</name>
</leaf>
</leaves>
<bugs uId="19"/>
</branch>
</branches>
<title uId="20">Great Tree</title>
</tree>
<tree>
<branches>
<branch>
<branchId>0988890098887656</branchId>
<number>7</number>
<leaves>
<leaf uId="8">
<name uId="9">Leaf 2</name>
</leaf>
</leaves>
<bugs>10</bugs>
</branch>
<branch>
<branchId>66677755564446</branchId>
<number/>
<leaves>
<leaf uId="17">
<name uId="18">Leaf 2</name>
</leaf>
</leaves>
<bugs/>
</branch>
</branches>
<title>Great Tree</title>
</tree>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.