[英]Loop XML nodes with grouping using XSLT 1.0
使用以下XML
<page>
<chunk id="1001" sequence="1">
<meta>Inline</meta>
<body>Inline chunk 1</body>
</chunk>
<chunk id="1002" sequence="2">
<meta>Tabs</meta>
<body>Tab chunk 1</body>
</chunk>
<chunk id="1054" sequence="3">
<meta>Tabs</meta>
<body>Tab chunk 2</body>
</chunk>
<chunk id="1023" sequence="4">
<meta>Inline</meta>
<body>Inline chunk 2</body>
</chunk>
<chunk id="1013" sequence="5">
<meta>Tabs</meta>
<body>Tab chunk 3</body>
</chunk>
<chunk id="1072" sequence="6">
<meta>Tabs</meta>
<body>Tab chunk 4</body>
</chunk>
</page>
我想應用XSL模板來輸出以下內容:
<main>
<section class="Inline>
<div>Inline chunk 1</div>
</section>
<section class="Tabs>
<div>Tab chunk 1</div>
<div>Tab chunk 2</div>
</section>
<section class="Inline>
<div>Inline chunk 2</div>
</section>
<section class="Tabs>
<div>Tab chunk 3</div>
<div>Tab chunk 4</div>
</section>
</main>
基本上,我想按./@sequence
的順序輸出chunk
,但在可能時根據其./meta
值對它們進行./meta
。 “可能”是指僅將它們具有相同的./meta
值並按順序排列在一起。
使用Muenchian方法,我可以將chunk
按./meta
,但只能得到以下結果:
<main>
<section class="Inline>
<div>Inline chunk 1</div>
<div>Inline chunk 2</div>
</section>
<section class="Tabs>
<div>Tab chunk 1</div>
<div>Tab chunk 2</div>
<div>Tab chunk 3</div>
<div>Tab chunk 4</div>
</section>
</main>
這是我使用的XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kBucketByLabel" match="/page/chunk" use="./meta" />
<!-- Then we override/define a template to match "/SAM" and write our body HTML here. -->
<xsl:template match="/page" mode="body">
<main>
<xsl:apply-templates select="chunk[generate-id() = generate-id( key('kBucketByLabel', ./meta)[1] )]" mode="bucket">
<xsl:sort select="@sequence" data-type="number" />
</xsl:apply-templates>
</main>
</xsl:template>
<xsl:template match="chunk" mode="bucket">
<xsl:variable name="bucket" select="./meta" />
<section class="{$bucket}">
<xsl:for-each select="key('kBucketByLabel', $bucket)">
<div><xsl:value-of select="./body"/></div>
</xsl:for-each>
</section>
</xsl:template>
</xsl:stylesheet>
一種實現方法是通過稱為“同級遞歸”的技術:
XSLT 1.0
<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="/page">
<main>
<xsl:apply-templates select="chunk[not(meta = preceding-sibling::chunk[1]/meta)]"/>
</main>
</xsl:template>
<xsl:template match="chunk">
<section class="{meta}">
<xsl:apply-templates select="." mode="collect"/>
</section>
</xsl:template>
<xsl:template match="chunk" mode="collect">
<div>
<xsl:value-of select="body"/>
</div>
<xsl:apply-templates select="following-sibling::chunk[1][meta = current()/meta]" mode="collect"/>
</xsl:template>
</xsl:stylesheet>
這可用於未分類的塊嗎? 在上面的示例數據中,我有意按
@sequence
對它們進行@sequence
,以便於可視化,但我的實際數據未排序。
...
我設法通過首先循環使用<xsl:for-each>
chunk
對它們進行排序,按@sequence
對其進行@sequence
,並將其副本存儲到RTF。 我不得不使用擴展將RTF轉換為節點集並應用您的技術。 它有效,但我希望盡可能不要這樣做。
實際上,這正是我要做的:首先對數據進行排序,將其轉換為節點集,然后在第二遍中應用上述方法。
如果您不想這樣做,則可以使用鍵來引用序列中的上一個/下一個塊,前提是該序列是連續的:
XSLT 1.0
<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:key name="chunk" match="chunk" use="@sequence" />
<xsl:template match="/page">
<main>
<xsl:apply-templates select="chunk[not(meta = key('chunk', @sequence - 1)/meta)]">
<xsl:sort select="@sequence" data-type="number" order="ascending"/>
</xsl:apply-templates>
</main>
</xsl:template>
<xsl:template match="chunk">
<section class="{meta}">
<xsl:apply-templates select="." mode="collect"/>
</section>
</xsl:template>
<xsl:template match="chunk" mode="collect">
<div>
<xsl:value-of select="body"/>
</div>
<xsl:apply-templates select="key('chunk', @sequence + 1)[meta = current()/meta]" mode="collect"/>
</xsl:template>
</xsl:stylesheet>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.