XSLT 1 将 ID 分组和组合到 csv
XSLT 1 Grouping and combining IDs to csv
我有以下 XML 文档,我喜欢按组标签对书籍进行分组,并使用 Java 和 将一个组的所有 ID(标题)合并为一个 csv XSLT 1.
我还希望有一个摘要元素,其中包含一个丛书的所有共享信息 (SeriesInfo) 以及每个组中的两个元素;一个(例如 Titles)包含该组的所有标题(ID)以逗号分隔 (csv),另一个(例如 AnyTitle)包含任何标题(哪个无关紧要,第一个或最后一个都可以)。
我已经通过 Muenchian Grouping 进行了分组,但不知道如何获取 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>
这会使用组标题的 comma-separated 列表填充 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])]">
<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>
我有以下 XML 文档,我喜欢按组标签对书籍进行分组,并使用 Java 和 将一个组的所有 ID(标题)合并为一个 csv XSLT 1.
我还希望有一个摘要元素,其中包含一个丛书的所有共享信息 (SeriesInfo) 以及每个组中的两个元素;一个(例如 Titles)包含该组的所有标题(ID)以逗号分隔 (csv),另一个(例如 AnyTitle)包含任何标题(哪个无关紧要,第一个或最后一个都可以)。
我已经通过 Muenchian Grouping 进行了分组,但不知道如何获取 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>
这会使用组标题的 comma-separated 列表填充 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])]">
<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>