【问题标题】:XSLT add child node and move children node outsideXSLT 添加子节点并将子节点移到外部
【发布时间】:2016-01-10 10:55:00
【问题描述】:

我在下面有一个输入 XML:

<Dogs>
   <Group Name="Cuties">
      <Dog Breed="Beagle">
         <Detail1>...</Detail1>
      </Dog>
      <Dog Breed="French Bulldog">
         <Detail1>...</Detail1>
      </Dog>
   </Group>
   <Group Name="Lovable">
      <Dog Breed="Labrador">
         <Detail1>...</Detail1>
      </Dog>
      <Dog Breed="Terrier">
         <Detail1>...</Detail1>
      </Dog>
   </Group>
   <Group Name="Bad">
      <Dog Breed="S">
         <Detail1>...</Detail1>
      </Dog>
      <Dog Breed="D">
         <Detail1>...</Detail1>
      </Dog>
   </Group>
</Dogs>

我想要的输出是在&lt;Dog&gt; 中添加另一个子节点并将它们移出&lt;Group&gt;。新的子节点应该是其组的Name 属性的值。这应该只影响CutiesLovable

<Dogs>
      <Dog Breed="Beagle">
         <Detail1>...</Detail1>
         <Detail2>Cuties</Detail2>
      </Dog>
      <Dog Breed="French Bulldog">
         <Detail1>...</Detail1>
         <Detail2>Cuties</Detail2>
      </Dog>
      <Dog Breed="Labrador">
         <Detail1>...</Detail1>
         <Detail2>Lovable</Detail2>
      </Dog>
      <Dog Breed="Terrier">
         <Detail1>...</Detail1>
         <Detail2>Lovable</Detail2>
      </Dog>
      <Group Name="Bad">
          <Dog Breed="S">
             <Detail1>...</Detail1>
          </Dog>
          <Dog Breed="D">
             <Detail1>...</Detail1>
          </Dog>
      </Group>
</Dogs>

我刚刚开始学习 XSLT,如果想弄清楚这一点会很有帮助

【问题讨论】:

    标签: xml xslt xslt-1.0


    【解决方案1】:

    从一个身份模板开始,然后添加一个模板来匹配应该在输出中省略的狗组:

    <xsl:template match="Group[@Name = 'Cuties' or @Name = 'Lovable']">
    

    另一个对这些组中的 Dog 元素进行特殊处理:

    <xsl:template match="Group[@Name = 'Cuties' or @Name = 'Lovable']/Dog">
    

    即添加一个Detail2 元素作为它们的最后一个子元素。

    XSLT 样式表

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    
        <xsl:output method="xml"  omit-xml-declaration="no" encoding="UTF-8" indent="yes" />
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="Group[@Name = 'Cuties' or @Name = 'Lovable']">
            <xsl:apply-templates/>
        </xsl:template>
    
        <xsl:template match="Group[@Name = 'Cuties' or @Name = 'Lovable']/Dog">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
                <Detail2>
                    <xsl:value-of select="../@Name"/>
                </Detail2>
            </xsl:copy>
        </xsl:template>
    
        <!--Identity template-->
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
    </xsl:transform>
    

    如果您使用的是 XSLT 2.0,Martin Honnen 建议您可以将第一个模板缩短为

    <xsl:template match="Group[@Name = ('Cuties','Lovable')]">
    

    如果@Name 的值与序列中的一个字符串相同,则谓词为真。

    XML 输出

    <?xml version="1.0" encoding="UTF-8"?>
    <Dogs>
       <Dog Breed="Beagle">
          <Detail1>...</Detail1>
          <Detail2>Cuties</Detail2>
       </Dog>
       <Dog Breed="French Bulldog">
          <Detail1>...</Detail1>
          <Detail2>Cuties</Detail2>
       </Dog>
       <Dog Breed="Labrador">
          <Detail1>...</Detail1>
          <Detail2>Lovable</Detail2>
       </Dog>
       <Dog Breed="Terrier">
          <Detail1>...</Detail1>
          <Detail2>Lovable</Detail2>
       </Dog>
       <Group Name="Bad">
          <Dog Breed="S">
             <Detail1>...</Detail1>
          </Dog>
          <Dog Breed="D">
             <Detail1>...</Detail1>
          </Dog>
       </Group>
    </Dogs>
    

    在线尝试此解决方案here


    编辑

    是身份模板的目的,照原样复制吗?

    是的,没错。如果 identy 模板是样式表中的唯一模板,则所有输入都将原封不动地复制。

    【讨论】:

    • 很好,因为您使用了version="2.0",您可以将谓词缩短为[@Name = ('Cuties', 'Lovable')]
    • 是身份模板的目的,照原样复制?
    • @MartinHonnen 感谢您的建议!由于我们不知道 OP 使用什么,所以我制作了样式表 1.0,但仍然指出了 XSLT 2.0 的简写。
    • 我使用版本 1,但感谢您也建议版本 2
    • @RojBeraña 你的意思是xsl:apply-templates 还是xsl:template?样式表中模板的顺序无关紧要。它们的工作方式大致是:对于输入中的每个项目,XSLT 处理器都会寻找与该项目最匹配的一个模板。只有这样,这个模板的内容才会被执行。另一方面,指令inside xsl:template(例如xsl:apply-templates)总是按顺序执行,从上到下。
    猜你喜欢
    • 2021-03-20
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多