使用 XSLT 对一些 XML 元素进行分组
Grouping some XML elements with XSLT
我在 XSLT 上苦苦挣扎了几个小时,我来到 Whosebug 寻求帮助。我有一些这样的输入文本:
<?xml version="1.0" encoding="UTF-8"?>
<div>
<p class="text">Some regular text</p>
<p class="first">The first part</p>
<p class="next">and then some text</p>
<p class="next">and some more</p>
<p class="regular">Some regular text</p>
<p class="text1">Some regular text</p>
<p class="text2">Some regular text</p>
<p class="first">Here some new text</p>
<p class="next">and some more</p>
<p class="next">and the end of this section</p>
<p class="text3">Some regular text</p>
</div>
我想以此结束
<?xml version="1.0" encoding="UTF-8"?>
<div>
<p>Some regular text</p>
<group>
<p>The first part</p>
<p>and then some text</p>
<p>and some more</p>
</group>
<p>Some regular text</p>
<p>Some regular text</p>
<p>Some regular text</p>
<group>
<p>Here some new text</p>
<p>and some more</p>
<p>and the end of this section</p>
</group>
<p>Some regular text</p>
</div>
我知道这并不难,但我不明白...我现在得到的 XSLT 是:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="/">
<xsl:apply-templates select="*" />
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:for-each select="@*">
<xsl:copy />
</xsl:for-each>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="div">
<lg>
<xsl:apply-templates/>
</lg>
</xsl:template>
<xsl:template match="/div">
<xsl:for-each-group select="//p[@class='first']/following-sibling::p[@class='next']" group-by="text()">
<group>
<xsl:apply-templates/>
</group>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
那根本行不通 :( 如果有人能帮助我,我将不胜感激,因为我真的很难理解 XSLT 的工作原理...
此致,
何塞
您正在尝试将 p
的 class
属性设置为 "first",然后是所有 "next"。
对于给定的 XML,此 XSLT 可以解决问题:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.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="/div">
<xsl:for-each-group select="p" group-adjacent="@class = 'first' or @class='next'">
<xsl:choose>
<xsl:when test="@class = 'first' or @class='next'">
<group>
<xsl:apply-templates select="current-group()" />
</group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="@class" />
</xsl:stylesheet>
但是,这在这种情况下不起作用,因为它会将所有 p
元素放在一个组中。
<div>
<p class="first">The first part</p>
<p class="next">and then some text</p>
<p class="first">Here some new text</p>
<p class="next">and some more</p>
</div>
如果这不是您想要的,请试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.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="/div">
<xsl:for-each-group select="p" group-starting-with="p[@class='first']">
<xsl:for-each-group select="current-group()" group-adjacent="@class='first' or @class='next'">
<xsl:choose>
<xsl:when test="@class='first' or @class='next'">
<group>
<xsl:apply-templates select="current-group()" />
</group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="@class" />
</xsl:stylesheet>
我在 XSLT 上苦苦挣扎了几个小时,我来到 Whosebug 寻求帮助。我有一些这样的输入文本:
<?xml version="1.0" encoding="UTF-8"?>
<div>
<p class="text">Some regular text</p>
<p class="first">The first part</p>
<p class="next">and then some text</p>
<p class="next">and some more</p>
<p class="regular">Some regular text</p>
<p class="text1">Some regular text</p>
<p class="text2">Some regular text</p>
<p class="first">Here some new text</p>
<p class="next">and some more</p>
<p class="next">and the end of this section</p>
<p class="text3">Some regular text</p>
</div>
我想以此结束
<?xml version="1.0" encoding="UTF-8"?>
<div>
<p>Some regular text</p>
<group>
<p>The first part</p>
<p>and then some text</p>
<p>and some more</p>
</group>
<p>Some regular text</p>
<p>Some regular text</p>
<p>Some regular text</p>
<group>
<p>Here some new text</p>
<p>and some more</p>
<p>and the end of this section</p>
</group>
<p>Some regular text</p>
</div>
我知道这并不难,但我不明白...我现在得到的 XSLT 是:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="/">
<xsl:apply-templates select="*" />
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:for-each select="@*">
<xsl:copy />
</xsl:for-each>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="div">
<lg>
<xsl:apply-templates/>
</lg>
</xsl:template>
<xsl:template match="/div">
<xsl:for-each-group select="//p[@class='first']/following-sibling::p[@class='next']" group-by="text()">
<group>
<xsl:apply-templates/>
</group>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
那根本行不通 :( 如果有人能帮助我,我将不胜感激,因为我真的很难理解 XSLT 的工作原理...
此致, 何塞
您正在尝试将 p
的 class
属性设置为 "first",然后是所有 "next"。
对于给定的 XML,此 XSLT 可以解决问题:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.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="/div">
<xsl:for-each-group select="p" group-adjacent="@class = 'first' or @class='next'">
<xsl:choose>
<xsl:when test="@class = 'first' or @class='next'">
<group>
<xsl:apply-templates select="current-group()" />
</group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="@class" />
</xsl:stylesheet>
但是,这在这种情况下不起作用,因为它会将所有 p
元素放在一个组中。
<div>
<p class="first">The first part</p>
<p class="next">and then some text</p>
<p class="first">Here some new text</p>
<p class="next">and some more</p>
</div>
如果这不是您想要的,请试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.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="/div">
<xsl:for-each-group select="p" group-starting-with="p[@class='first']">
<xsl:for-each-group select="current-group()" group-adjacent="@class='first' or @class='next'">
<xsl:choose>
<xsl:when test="@class='first' or @class='next'">
<group>
<xsl:apply-templates select="current-group()" />
</group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="@class" />
</xsl:stylesheet>