将XML节点一分为二(XSLT转换)

时间:2018-11-23 11:15:22

标签: xml xslt-1.0

请帮助您如何将半节点与子节点拆分。

输入:

<RuleCollection Type="Exe" EnforcementMode="Enabled">
 <FileHashRule Id="1">
  <Conditions>
   <FileHashCondition>
    <FileHash Type="SHA256" Data="0xCC864"></FileHash>
    <FileHash Type="SHA256" Data="0x9D973"></FileHash>
    <FileHash Type="SHA256" Data="0xA92EF"></FileHash>
    <FileHash Type="SHA256" Data="0x279CD"></FileHash>
   </FileHashCondition>
  </Conditions>
 </FileHashRule>
</RuleCollection>

输出:

<RuleCollection Type="Exe" EnforcementMode="Enabled">
 <FileHashRule Id="hard-coded guid1">
  <Conditions>
   <FileHashCondition>
    <FileHash Type="SHA256" Data="0xCC864"></FileHash>
    <FileHash Type="SHA256" Data="0x9D973"></FileHash>
   </FileHashCondition>
  </Conditions>
 </FileHashRule>
 <FileHashRule Id="hard-coded guid2">
  <Conditions>
   <FileHashCondition>
    <FileHash Type="SHA256" Data="0xA92EF"></FileHash>
    <FileHash Type="SHA256" Data="0x279CD"></FileHash>
   </FileHashCondition>
  </Conditions>
 </FileHashRule>
</RuleCollection>

不幸的是,我对xslt没有经验,也没有找到这样的示例。

已更新 我尝试了以下建议的方法之一,并且使此https://xsltfiddle.liberty-development.net/jyH9rNq/3节点不会复制

xslt:

            <?xml version="1.0" encoding="UTF-8"?>
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" indent="yes"/>

        <xsl:variable name="fileHash" select="/FileHashRule/Conditions/FileHashCondition/FileHash" />
        <xsl:variable name="half" select="count($fileHash) div 2" />

        <xsl:template match="/">
        <RuleCollection>
            <FileHashRule>
                <xsl:attribute name="Id">ad22d301-eb88-485d-ae1d-537790bdebfa</xsl:attribute>
                    <Conditions>

                        <FileHashCondition>
                        <xsl:copy-of select="$fileHash[position() &lt;= $half]" />

                        </FileHashCondition>
                    </Conditions>
            </FileHashRule>

                <FileHashRule>
                <xsl:attribute name="Id">ad22d301-eb88-485d-ae1d-537790bdebfb</xsl:attribute>
                    <Conditions>

                        <FileHashCondition>
                        <xsl:copy-of select="$fileHash[position() &gt; $half]" />
                        </FileHashCondition>
                    </Conditions>
            </FileHashRule>


        </RuleCollection>
        </xsl:template>

        </xsl:stylesheet>   

输出:

        <?xml version="1.0" encoding="UTF-8"?>
    <RuleCollection>
       <FileHashRule Id="ad22d301-eb88-485d-ae1d-537790bdebfa">
          <Conditions>
             <FileHashCondition/>
          </Conditions>
       </FileHashRule>
       <FileHashRule Id="ad22d301-eb88-485d-ae1d-537790bdebfb">
          <Conditions>
             <FileHashCondition/>
          </Conditions>
       </FileHashRule>
    </RuleCollection>

3 个答案:

答案 0 :(得分:1)

您可以从(XSLT Fiddle)开始:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="//xs">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select='x[position() &lt;= last() div 2]'/>
    </xsl:copy>

    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select='x[position() &gt; last() div 2]'/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@* | node()">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

它将分裂

<?xml version="1.0" encoding="utf-8" ?>
<data>
    <xs a="b">
        <will-not-be-copied/>
        <x>1</x>
        <x>2</x>
        <x>3</x>
        <x>4</x>
    </xs>
</data>

进入

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <xs a="b">
      <x>1</x>
      <x>2</x>
   </xs>
   <xs a="b">
      <x>3</x>
      <x>4</x>
   </xs>
</data>

不过请注意,您需要弄清楚如何处理诸如<will-not-be-copied>之类的标记,并且可能希望将id值添加到拆分的<xs>标记中。

答案 1 :(得分:0)

您可以通过以下方法很简单地找到一半:

<xsl:variable name="fileHash" select="/RuleCollection/FileHashRule/Conditions/FileHashCondition/FileHash" />
<xsl:variable name="half" select="count($fileHash) div 2" />

然后只需创建两个FileHashRule元素并使用:

<xsl:copy-of select="$fileHash[position() &lt;= $half]" />

填充第一个,并且:

<xsl:copy-of select="$fileHash[position() &gt; $half]" />

第二个。

答案 2 :(得分:0)

这是一种方法:

<xsl:template match="@*|node()" mode="#all">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()" mode="#current"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="FileHashRule">
  <FileHashRule Id="{@Id}">
    <xsl:apply-templates mode="one"/>
  </FileHashRule>
  <FileHashRule Id="{@Id + 1}">
    <xsl:apply-templates mode="two"/>
  </FileHashRule>
</xsl:template>

<xsl:template match="FileHash[position() > last() div 2]" mode="one"/>
<xsl:template match="FileHash[position() &lt;= last() div 2]" mode="two"/>

第一条规则说:默认情况下,复制节点不变。

第二个规则说:对于FileHashRule,创建两个副本,在第二个中增加@Id属性。

第三条规则说:在第一阶段,跳过列表后半部分的任何FileHash元素。

第四条规则说:在第二阶段,跳过列表上半部分的任何FileHash元素。