用于XML过滤的XSLT

时间:2014-05-15 21:39:53

标签: xml xslt

我是XSLT的新手 - 我正在尝试利用它来根据指定的属性重新创建(复制)现有的xml文档。

作为一个例子,使用以下XML,我想从mainGroup获得具有属性为group =“Book1”的属性tags =“6”的课程

<Groups>
<mainGroup id="1" group="Book1">
<subGroup name="Chapter 1">
    <lesson name="Lesson1" tags="1" />
    <lesson name="Lesson2" tags="2" />
</subGroup>
<subGroup name="Chapter 2">
    <lesson name="Lesson1" tags="3" />
    <lesson name="Lesson2" tags="4" />
</subGroup>
<subGroup name="Chapter 3">
    <subGroup name="Chapter 3 Examples">
        <lesson name="Lesson2" tags="5" />
    </subGroup>
    <lesson name="Lesson1" tags="6" />
</subGroup>
</mainGroup>
<mainGroup id="1" group="Book2">
<subGroup name="Chapter 1">
    <lesson name="Lesson1" tags="1" />
    <lesson name="Lesson2" tags="2" />
</subGroup>
<subGroup name="Chapter 2">
    <lesson name="Lesson1" tags="3" />
    <lesson name="Lesson2" tags="4" />
</subGroup>
<subGroup name="Chapter 3">
    <subGroup name="Chapter 3 Examples">
        <lesson name="Lesson2" tags="6" />
    </subGroup>
    <lesson name="Lesson1" tags="5" />
</subGroup>
</mainGroup>
</Groups>

在应用XSL后具有以下预期(预期)结果

<Groups>
<mainGroup id="1" group="Book1">
<subGroup name="Chapter 3">
    <lesson name="Lesson1" tags="6" />
</subGroup>
</mainGroup>
 </Groups>

就XSL而言,到目前为止,我所提出的最接近的是:

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


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


// Remove all maingroups that are not book1
 <xsl:template match="mainGroup[not(@group='Book1')]" />

// Remove all lessons that do not have tags of 5
 <xsl:template match="lesson[not(@tags='5')]" />

</xsl:stylesheet>

给出了XML结果:

<Groups>
   <mainGroup id="1" group="Book1">
      <subGroup name="Chapter 1" />
      <subGroup name="Chapter 2" />
      <subGroup name="Chapter 3">
         <subGroup name="Chapter 3 Examples">
            <lesson name="Lesson2" tags="5" />
         </subGroup>
      </subGroup>
   </mainGroup>
</Groups>

我无法弄清楚如何删除空的子组 -

我尝试过的一些事情(再次请不要笑 - 这个XSL的新内容:))

希望这删除那些没有课程节点的人 - 但似乎没有做任何事情

 <xsl:template match="subGroup[count(lesson) = 0]" />

 <xsl:template match="subGroup[not(node())]" />

甚至是这样的事情---

<xsl:template match="subGroups" mode="copy">
     <xsl:choose>
       <xsl:when test="count(./*)">
         <xsl:copy>
           <xsl:apply-templates select="@*|node()" mode="copy"/>
         </xsl:copy>
       </xsl:when>
       <xsl:otherwise>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:template>

但是经过几个小时的没有成功之后我就撇下了 - 我敢肯定有人在这里读这个想法 - 啊,你只需要添加或做到这一点 - 所以任何帮助都会受到赞赏。< / p>

由于

2 个答案:

答案 0 :(得分:1)

关键是模板规则与输入 XML匹配,因此您必须取消那些不包含您想要的课程的subGroup元素:

<xsl:template match="subGroup[not(.//lesson/@tags = '5')]"/>

对于哪些子组最终将为空的规则更复杂的情况,可能更容易进行两阶段转换,第一次通过,当前正在进行,然后第二次通过处理第一个删除剩余空标签的结果。在XSLT 2.0中,这很简单

<xsl:variable name="pass1">
  <xsl:apply-templates />
</xsl:variable>
<xsl:apply-templates select="$pass1" mode="pass2"/>

但在1.0中它需要node-set扩展功能。如果你想走这条路,你可以在其他问题中找到很多这种技术的例子。

答案 1 :(得分:1)

不是购买批发商品,而是试图摆脱你不需要的东西,为什么不首先选择你需要的东西呢?

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

<xsl:template match="/Groups">
    <xsl:copy>
        <xsl:apply-templates select="mainGroup[@group='Book1']"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="mainGroup">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="subGroup[lesson[@tags='6']]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="subGroup">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:copy-of select="lesson[@tags='6']"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

或者,如果您愿意:

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

<xsl:template match="/">
    <Groups>
        <xsl:for-each select="Groups/mainGroup[@group='Book1']/subGroup/lesson[@tags='6']">
            <mainGroup>
                <xsl:copy-of select="../../@*"/>
                <subGroup>
                    <xsl:copy-of select="../@*"/>
                    <xsl:copy-of select="."/>
                </subGroup>
            </mainGroup>
        </xsl:for-each>
    </Groups>
</xsl:template>

</xsl:stylesheet>