我有以下XML文档,喜欢按组标记对书籍进行分组,并使用Java和XSLT 1将组的所有ID(标题)组合到一个csv中。
此外,我希望有一个summary元素,其中包含书籍系列的所有共享信息(SeriesInfo)以及每个组中的两个元素;一个(例如标题)包含此组的所有标题(ID),以逗号分隔(csv),另一个(例如AnyTitle)包含任何标题。
我已经设法通过Muenchian分组进行分组,但是不知道如何获取csv和any元素。我已经对此进行了一些研究,但是我发现的解决方案要么非常具体,要么使用XSLT 2或更高版本。
源XML
<?xml version="1.0" encoding="UTF-8"?>
<Books>
<Book>
<Title>Harry Potter and the philosopher's stone</Title>
<Group>Harry Potter</Group>
<Author>J.K.R.</Author>
<Pages>650</Pages>
</Book>
<Book>
<Title>Harry Potter and the chamber of secrets</Title>
<Group>Harry Potter</Group>
<Author>J.K.R.</Author>
<Pages>700</Pages>
</Book>
<Book>
<Title>Lord of the Rings complete edition</Title>
<Group>Lord of the Rings</Group>
<Author>J.R.R. Tolkien</Author>
<Pages>2500</Pages>
</Book>
</Books>
目标XML
<?xml version="1.0" encoding="UTF-8"?>
<Serieses>
<Series>
<Group>Harry Potter</Group>
<Titles>Harry Potter and the philosopher's stone,Harry Potter and the chamber of secrets</Titles>
<AnyTitle>Harry Potter and the chamber of secrets</AnyTitle>
<Books>
<Book>
<Title>Harry Potter and the philosopher's stone</Title>
<Group>Harry Potter</Group>
<Pages>650</Pages>
</Book>
<Book>
<Title>Harry Potter and the chamber of secrets</Title>
<Group>Harry Potter</Group>
<Pages>700</Pages>
</Book>
</Books>
<SeriesInfo>
<Author>J.K.R.</Author>
<Group>Harry Potter</Group>
</SeriesInfo>
</Series>
<Series>
<Group>Lord of the Rings</Group>
<Titles>Lord of the Rings complete edition</Titles>
<AnyTitle>Lord of the Rings complete edition</AnyTitle>
<Books>
<Book>
<Title>Lord of the Rings complete edition</Title>
<Group>Lord of the Rings</Group>
<Pages>2500</Pages>
</Book>
</Books>
<SeriesInfo>
<Author>J.R.R. Tolkien</Author>
<Group>Lord of the Rings</Group>
</SeriesInfo>
</Series>
</Serieses>
使用以下XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="book-by-name" match="Book" use="Group" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Books">
<Serieses>
<xsl:apply-templates
select="Book[generate-id() = generate-id(key('book-by-name', Group)[1])]"
mode="group" />
</Serieses>
</xsl:template>
<xsl:template match="Book" mode="group">
<Series>
<xsl:copy-of select="Group" />
<Books>
<xsl:apply-templates
select="key('book-by-name', Group)" />
</Books>
<SeriesInfo>
<xsl:copy-of select="Author" />
<xsl:copy-of select="Group" />
</SeriesInfo>
</Series>
</xsl:template>
<xsl:template match="Book">
<Book>
<xsl:apply-templates
select="node()[self::Title|self::Group|self::Pages]" />
</Book>
</xsl:template>
</xsl:stylesheet>
我能够获得以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<Serieses>
<Series>
<Group>Harry Potter</Group>
<Books>
<Book>
<Title>Harry Potter and the philosopher's stone</Title>
<Group>Harry Potter</Group>
<Pages>650</Pages>
</Book>
<Book>
<Title>Harry Potter and the chamber of secrets</Title>
<Group>Harry Potter</Group>
<Pages>700</Pages>
</Book>
</Books>
<SeriesInfo>
<Author>J.K.R.</Author>
<Group>Harry Potter</Group>
</SeriesInfo>
</Series>
<Series>
<Group>Lord of the Rings</Group>
<Books>
<Book>
<Title>Lord of the Rings complete edition</Title>
<Group>Lord of the Rings</Group>
<Pages>2500</Pages>
</Book>
</Books>
<SeriesInfo>
<Author>J.R.R. Tolkien</Author>
<Group>Lord of the Rings</Group>
</SeriesInfo>
</Series>
</Serieses>
使用XSLT的任何最新版本对我并没有太大帮助,因为我需要依赖标准库。
这里是您可以查看的一种方式:
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:strip-space elements="*"/>
<xsl:key name="book-by-group" match="Book" use="Group" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/Books">
<Serieses>
<xsl:apply-templates select="Book[generate-id() = generate-id(key('book-by-group', Group)[1])]" mode="group" />
</Serieses>
</xsl:template>
<xsl:template match="Book" mode="group">
<xsl:variable name="current-group" select="key('book-by-group', Group)" />
<Series>
<xsl:apply-templates select="Group" />
<Titles>
<xsl:apply-templates select="$current-group" mode="Title"/>
</Titles>
<AnyTitle>
<xsl:value-of select="$current-group[1]/Title"/>
</AnyTitle>
<Books>
<xsl:apply-templates select="$current-group" />
</Books>
<SeriesInfo>
<xsl:apply-templates select="Author" />
<xsl:apply-templates select="Group" />
</SeriesInfo>
</Series>
</xsl:template>
<xsl:template match="Book">
<Book>
<xsl:apply-templates select="Title | Group| Pages" />
</Book>
</xsl:template>
<xsl:template match="Book" mode="Title">
<xsl:value-of select="Title"/>
<xsl:if test="position() != last()">,</xsl:if>
</xsl:template>
</xsl:stylesheet>
这将用逗号分隔的组标题列表填充Titles
元素。对于AnyTitle
元素,我选择了该组中第一本书的标题。
个人,我希望将整个内容缩短为:
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:strip-space elements="*"/>
<xsl:key name="book-by-group" match="Book" use="Group" />
<xsl:template match="/Books">
<Serieses>
<xsl:for-each select="Book[generate-id() = generate-id(key('book-by-group', Group)[1])]" mode="group" >
<xsl:variable name="current-group" select="key('book-by-group', Group)" />
<Series>
<xsl:copy-of select="Group" />
<Titles>
<xsl:for-each select="$current-group">
<xsl:value-of select="Title"/>
<xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
</Titles>
<AnyTitle>
<xsl:value-of select="$current-group[1]/Title"/>
</AnyTitle>
<Books>
<xsl:for-each select="$current-group">
<xsl:copy>
<xsl:copy-of select="Title | Group| Pages" />
</xsl:copy>
</xsl:for-each>
</Books>
<SeriesInfo>
<xsl:copy-of select="Author" />
<xsl:copy-of select="Group" />
</SeriesInfo>
</Series>
</xsl:for-each>
</Serieses>
</xsl:template>
</xsl:stylesheet>