简体   繁体   English

XSLT从子节点创建父节点的副本

[英]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. 第一棵树在叶子下保存第一个叶子节点,第二棵树在叶子下保存第二个叶子节点。

Before XML Image 在XML映像之前

After XML Image XML图像之后

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 &lt;= $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: 另一种方法是:

  • Create a key of leaf 's based on their position. 根据leaf的位置创建一个键。
  • Process the first leaf for each key. 处理每个密钥的第一leaf ( Muenchian Grouping ) Muenchian分组
  • The first leaf in a key triggers processing of the ancestor tree (and its descendants). 键中的第一个叶子触发对祖先树(及其后代)的处理。
  • A list of generated ID's for all of the 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调用中传递它。)
  • When the leaves element is processed, only leaf elements with a matching generated ID are processed. 处理leaves元素时,仅处理具有匹配的生成ID的leaf元素。
  • The use of 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM