【问题标题】:split XML node by half (XSLT transformation)将 XML 节点一分为二(XSLT 转换)
【发布时间】:2019-04-26 00:08:09
【问题描述】:

能否请您帮助如何将子节点分成两半。

输入:

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

【问题讨论】:

  • 定义“一半”,尤其是。在奇数节点的情况下。 -- 另请注意,您显示的输出不是格式良好的 XML(缺少单个根元素)。
  • @michael.hor257k,已更正,大约一半,没关系
  • 当你学习一门新语言时,你不需要经验,也不需要一个例子来解决你正在解决的确切问题,你需要一本好书或教程来教授概念,你应该先通过简单的练习来学习,然后再尝试解决更困难的问题。
  • 您不断更改输入 XML 格式。现在您已经添加了 RuleCollection 包装器,您必须将 fileHash 变量定义更改为:&lt;xsl:variable name="fileHash" select="/RuleCollection/FileHashRule/Conditions/FileHashCondition/FileHash" /&gt; - 请参阅:xsltfiddle.liberty-development.net/jyH9rNq/4
  • @michael.hor257k,非常感谢,效果很好。我需要什么

标签: xml xslt-1.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>

但请注意,您需要明确如何处理 &lt;will-not-be-copied&gt; 等标签,并且您可能希望将 id 值添加到拆分后的 &lt;xs&gt; 标签中。

【讨论】:

  • 您的包装器是相同的 - 与预期的输出不同。
【解决方案2】:

你可以很简单地找到半点:

<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]" />

第二个。

【讨论】:

    【解决方案3】:

    这是一种方法:

    <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 元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-16
      • 1970-01-01
      • 2013-02-17
      • 1970-01-01
      • 2011-10-05
      • 2011-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多