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

时间:2018-01-15 15:19:29

标签: xml xslt

我正在使用XSLT,我要求我不确定如何继续。

我在下面列出了图片,因为这个场景有点难以解释。

之前:有1个树节点,每个节点中有2个叶子节点。

之后:有2个树节点。第一棵树在叶子下面保存第一个叶子节点,第二棵树在叶子下面保存第二个叶子节点。

Before XML Image

After XML Image

我不确定我是否应该向外走,树 - >叶子或向内,叶子 - >我的模板匹配中的树..

感谢您的帮助!

更新

在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>

以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:

<?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>

到目前为止,我的XSLT复制树节点(每个分支的叶节点中的叶节点数)次。下一步是从树1中删除位置1处的叶子,从树2中删除位置2处的叶子...等,然后从原始树的任何副本中删除uid属性。

1 个答案:

答案 0 :(得分:0)

另一种方法是:

  • 根据位置创建leaf的密钥。
  • 处理每个密钥的第一个leaf。 (Muenchian Grouping
  • 键中的第一个叶子触发祖先树(及其后代)的处理。
  • 密钥中所有leaf生成的ID列表将作为参数传递。 (由于XSLT 1.0不支持隧道,因此需要在每个apply-templates调用中传递它。)
  • 处理leaves元素时,仅处理具有匹配生成ID的leaf个元素。
  • 使用mode可以控制是否处理属性。

示例(此处也演示了:http://xsltfiddle.liberty-development.net/6qM2e2a)...

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

<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>

<强>输出

<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>