我是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>
由于
答案 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>