【问题标题】:XSLT-1.0 | Get first and last node and call specific templateXSLT-1.0 |获取第一个和最后一个节点并调用特定模板
【发布时间】:2019-06-04 16:05:03
【问题描述】:

我对 XLST 比较陌生,这可能是一个典型的初学者问题,但我无法弄清楚。 希望你能帮助和理解我。先感谢您。 :-)

我尝试将一个大的 XML 文件转换为另一个文件,但不知道如何获取第一个和最后一个节点并将它们与其他节点包围。

问题是所有fruit节点都是迭代创建的。

在我看来,我应该在创建所有 fruits - 元素之后添加周围的 fruits - 节点。

我已经尝试过类似的方法:

<xsl:template name="tplFruit" match="PARENT_FRUIT">
   <xsl:apply-template select="(//element[@name='fruit'])[1]" />
</xsl:template>

<xsl:template name="addFruits">
   <fruits>
</xsl:template>
<xsl:template name="tplFruit" match="PARENT_FRUIT">
   <xsl:apply-template select="(//element[@name='fruit'])[last()]" />
</xsl:template>

<xsl:template name="addFruits">
   </fruits>
</xsl:template>

但它不起作用,我很确定会发生另一个错误,因为我在不同的模板中打开和关闭元素 fruits

给出以下 xml(输入 - XML):

<root>
... other elements ...

<PARENT_FRUIT>
   <different_node nr="1" />
   <different_node nr="2" />
   <different_node nr="3" />

   <fruit>
      <name>Apple</name>
      <calorien>999</calorien>
      <color>red</color>
   </fruit>
   <fruit>      
      <name>cherry</name>
      <calorien>999</calorien>
      <color>red</color></fruit>
   <fruit>
      <name>banana</name>
      <calorien>999</calorien>
      <color>red</color>
   </fruit>

   <different_node nr="4" />
   <different_node nr="5" />
   <different_node nr="6" />

   <fruit>
      <name>Apple2</name>
      <calorien>999</calorien>
      <color>red</color>
   </fruit>
   <fruit>
      <name>cherry2</name>
      <calorien>999</calorien>
      <color>red</color>
   </fruit>
   <fruit>
      <name>banana2</name>
      <calorien>999</calorien>
      <color>red</color>
   </fruit>

...and so on...
</PARENT_FRUIT>

...other elements ...
</root>

以下 XML 应该是我的最终结果:

<root>
... other elements ...

<PARENT_FRUIT>
... other elements ...

<fruits>
   <fruit>
      <name>apple</name>
      <calorien>999</carlorien>
      <color>red</color>
   </fruit>
   <fruit>
      <name>cherry</name>
      <calorien>999</carlorien>
      <color>red</color>
   </fruit>
   <fruit>
      <name>banana</name>
      <calorien>999</carlorien>
      <color>red</color>
   </fruit>
   <fruit>
      <name>apple2</name>
      <calorien>999</carlorien>
      <color>red</color>
   </fruit>
   <fruit>
      <name>cherry2</name>
      <calorien>999</carlorien>
      <color>red</color>
   </fruit>
   <fruit>
      <name>banana2</name>
      <calorien>999</carlorien>
      <color>red</color>
   </fruit>

... and so on ...
<fruits>

... other elements ...
<PARENT_FRUIT>

... other elements ...
</root>

编辑 04.06.2019:

我使用 XLST 1.0 版

【问题讨论】:

  • 您在哪里说“给出了以下 xml”,是您输入的 XML,还是您当前的输出?我确实注意到您的 XSLT 有一个匹配 PARENT_FRUIT 的模板,并且还尝试选择 element 元素,这表明您的输入 XML 是不同的,所以如果您展示它会有所帮助。谢谢!
  • @Tim C 更新了我原来的问题。不幸的是,由于数据保护,我无法显示我的原始输入 XML,它会超过 500 万行。
  • 我通过将 carlorien 更改为 calorien 修复了您的输入 XML。现在它是格式良好的
  • 从期望的结果中不清楚你所说的 firstlast 是什么意思。我所看到的只是包含在一个新的 fruits 元素内的所有 fruit 节点。不确定是否需要删除或重新定位兄弟 different_node
  • @Parfait 我只是想把水果元素括起来,其他属性应该重新定位。

标签: xml xslt xslt-1.0


【解决方案1】:

如果您可以在开始时将所有其他元素分组,那么以下简单的 XSLT-1.0 样式表就可以完成这项工作。否则将不清楚您要将&lt;fruits&gt; 元素放在哪里。

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

    <xsl:template match="PARENT_FRUIT">
        <xsl:copy>
            <xsl:apply-templates select="*[not(self::fruit)]|@*"/>
            <fruits>
                <xsl:apply-templates select="fruit"/>
            </fruits>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

它的输出是:

<?xml version="1.0"?>
<root>
    ... other elements ...

    <PARENT_FRUIT>
        <different_node nr="1"/>
        <different_node nr="2"/>
        <different_node nr="3"/>
        <different_node nr="4"/>
        <different_node nr="5"/>
        <different_node nr="6"/>
        <fruits><fruit>
                <name>Apple</name>
                <calorien>999</calorien>
                <color>red</color>
            </fruit>
            <fruit>      
                <name>cherry</name>
                <calorien>999</calorien>
                <color>red</color>
            </fruit>
            <fruit>
                <name>banana</name>
                <calorien>999</calorien>
                <color>red</color>
            </fruit>
            <fruit>
                <name>Apple2</name>
                <calorien>999</calorien>
                <color>red</color>
            </fruit>
            <fruit>
                <name>cherry2</name>
                <calorien>999</calorien>
                <color>red</color>
            </fruit>
            <fruit>
                <name>banana2</name>
                <calorien>999</calorien>
                <color>red</color>
            </fruit>
        </fruits>
    </PARENT_FRUIT>

    ...other elements ...
</root>

【讨论】:

    【解决方案2】:

    您可以匹配 fruit[1] 并将所有 fruit 元素包装到 fruits 容器中并匹配其他 fruit 元素以不处理它们:

    <xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">
    
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="fruit[1]">
          <fruits>
              <xsl:copy-of select="../fruit"/>
          </fruits>
      </xsl:template>
    
      <xsl:template match="fruit[position() > 1]"/>
    
    </xsl:stylesheet>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      • 2019-03-20
      相关资源
      最近更新 更多