xslt 分组和删除重复项
xslt grouping and removing duplicates
<Items>
<array>
<item name="A">
<name>A</name>
<indate>20141112</indate>
<inno>2</inno>
<status>1</status>
<level>12</level>
<size>.1</size>
<text>item a text </text>
</item>
<item name="B">
<name>B</name>
<indate>20141012</indate>
<inno>5</inno>
<status>1</status>
<level>13</level>
<size>.5</size>
<text>item b text </text>
</item>
<item name="C">
<name>C</name>
<indate>20140912</indate>
<inno>6</inno>
<status>1</status>
<level>12</level>
<size>.2</size>
<text>item c text </text>
</item>
<item name="A">
<name>A</name>
<ondate>20140612</ondate>
<onno>9</onno>
</item>
<item name="B">
<name>B</name>
<ondate>20140212</ondate>
<inno>7</inno>
</item>
<item name="D">
<name>D</name>
<indate>20140712</indate>
<inno>9</inno>
</item>
<item name="A">
<name>A</name>
<status>1</status>
<level>12</level>
<size>.1</size>
<text>item a text </text>
</item>
<item name="B">
<name>B</name>
<status>1</status>
<level>13</level>
<size>.5</size>
<text>item b text </text>
</item>
<item name="D">
<name>D</name>
<status>1</status>
<level>13</level>
<size>.9</size>
<text>item d text </text>
</item>
</array>
</Items>
我有这个 xml 我需要将它分组到以下输出并添加 inno 和 onno 元素以提供 sumno。并检查 indate 和 ondate 以提供更大的延迟。并在 inno/onno/indate/ondate 不存在时给出空元素。并删除重复项。如何用 muenchian 方法写这个
输出:
<Items>
<array>
<item name="A">
<name>A</name>
<indate>20141112</indate>
<inno>2</inno>
<ondate>20140612</ondate>
<onno>9</onno>
<latedate>20141112</latedate>
<sumno>11</sumno>
<status>1</status>
<level>12</level>
<size>.1</size>
<text>item a text </text>
</item>
<item name="B">
<name>B</name>
<indate>20141012</indate>
<inno>5</inno>
<ondate>20140212</ondate>
<onno>7</onno>
<latedate>20141012</latedate>
<sumno>12</sumno>
<status>1</status>
<level>13</level>
<size>.5</size>
<text>item b text </text>
</item>
<item name="C">
<name>C</name>
<indate>20140912</indate>
<inno>6</inno>
<ondate/>
<onno/>
<latedate>20140912</latedate>
<sumno>6</sumno>
<status>1</status>
<level>12</level>
<size>.2</size>
<text>item c text </text>
</item>
<item name="D">
<name>D</name>
<indate/>
<inno/>
<ondate>20140712</ondate>
<onno>7</onno>
<latedate>20140712</latedate>
<sumno>7</sumno>
<status>1</status>
<level>13</level>
<size>.9</size>
<text>item d text </text>
</item>
</array>
</Items>
我使用此 xsl 进行分组,但无法添加和删除重复项
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:output method="xml" indent="yes"/>
<xsl:key name="items-by-id" match="item[@name]" use="name"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="array">
<xsl:copy>
<xsl:apply-templates select="item[@name][generate-id() = generate-id(key('items-by-id', name)[1])]" mode="group"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[@name]" mode="group">
<xsl:copy>
<xsl:copy-of select="name"/>
<xsl:apply-templates select="key('items-by-id', name)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[@name]">
<xsl:apply-templates select="node()[not(self::name)]"/>
</xsl:template>
</xsl:stylesheet>
我认为您的代码确实按 name
子元素对 item
元素进行了正确分组。您似乎还想消除重复的子元素,我不确定您是想仅通过元素名称还是通过元素名称和元素内容来消除重复的子元素。如果你想通过元素名称来完成,那么你可以定义第二个键 <xsl:key name="duplicated-elements" match="item/*" use="concat(../name, '|', local-name())"/>
。
至于添加空元素,你需要检查它们是否存在。
这是带有此类检查的样式表和第二个键:
<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="items-by-id" match="item[@name]" use="name"/>
<xsl:key name="duplicated-elements" match="item/*" use="concat(../name, '|', local-name())"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="array">
<xsl:copy>
<xsl:apply-templates select="item[@name][generate-id() = generate-id(key('items-by-id', name)[1])]" mode="group"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[@name]" mode="group">
<xsl:copy>
<xsl:variable name="current-group" select="key('items-by-id', name)"/>
<xsl:copy-of select="name"/>
<xsl:choose>
<xsl:when test="$current-group/indate">
<xsl:apply-templates select="$current-group/indate"/>
</xsl:when>
<xsl:otherwise>
<indate/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="$current-group/inno">
<xsl:apply-templates select="$current-group/inno"/>
</xsl:when>
<xsl:otherwise>
<inno/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="$current-group/ondate">
<xsl:apply-templates select="$current-group/ondate"/>
</xsl:when>
<xsl:otherwise>
<ondate/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="$current-group/onno">
<xsl:apply-templates select="$current-group/onno"/>
</xsl:when>
<xsl:otherwise>
<onno/>
</xsl:otherwise>
</xsl:choose>
<latedate>
<xsl:choose>
<xsl:when test="$current-group/indate > $current-group/ondate">
<xsl:value-of select="$current-group/indate"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$current-group/ondate"/>
</xsl:otherwise>
</xsl:choose>
</latedate>
<sumno>
<xsl:value-of select="sum($current-group/inno | $current-group/onno)"/>
</sumno>
<xsl:apply-templates select="key('items-by-id', name)/*[not(self::name | self::indate | self::inno | self::ondate | self::onno)][generate-id() = generate-id(key('duplicated-elements', concat(../name, '|', local-name()))[1])]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
还有一些问题,比如检查不存在的日期,但我希望你能解决它。
<Items>
<array>
<item name="A">
<name>A</name>
<indate>20141112</indate>
<inno>2</inno>
<status>1</status>
<level>12</level>
<size>.1</size>
<text>item a text </text>
</item>
<item name="B">
<name>B</name>
<indate>20141012</indate>
<inno>5</inno>
<status>1</status>
<level>13</level>
<size>.5</size>
<text>item b text </text>
</item>
<item name="C">
<name>C</name>
<indate>20140912</indate>
<inno>6</inno>
<status>1</status>
<level>12</level>
<size>.2</size>
<text>item c text </text>
</item>
<item name="A">
<name>A</name>
<ondate>20140612</ondate>
<onno>9</onno>
</item>
<item name="B">
<name>B</name>
<ondate>20140212</ondate>
<inno>7</inno>
</item>
<item name="D">
<name>D</name>
<indate>20140712</indate>
<inno>9</inno>
</item>
<item name="A">
<name>A</name>
<status>1</status>
<level>12</level>
<size>.1</size>
<text>item a text </text>
</item>
<item name="B">
<name>B</name>
<status>1</status>
<level>13</level>
<size>.5</size>
<text>item b text </text>
</item>
<item name="D">
<name>D</name>
<status>1</status>
<level>13</level>
<size>.9</size>
<text>item d text </text>
</item>
</array>
</Items>
我有这个 xml 我需要将它分组到以下输出并添加 inno 和 onno 元素以提供 sumno。并检查 indate 和 ondate 以提供更大的延迟。并在 inno/onno/indate/ondate 不存在时给出空元素。并删除重复项。如何用 muenchian 方法写这个
输出:
<Items>
<array>
<item name="A">
<name>A</name>
<indate>20141112</indate>
<inno>2</inno>
<ondate>20140612</ondate>
<onno>9</onno>
<latedate>20141112</latedate>
<sumno>11</sumno>
<status>1</status>
<level>12</level>
<size>.1</size>
<text>item a text </text>
</item>
<item name="B">
<name>B</name>
<indate>20141012</indate>
<inno>5</inno>
<ondate>20140212</ondate>
<onno>7</onno>
<latedate>20141012</latedate>
<sumno>12</sumno>
<status>1</status>
<level>13</level>
<size>.5</size>
<text>item b text </text>
</item>
<item name="C">
<name>C</name>
<indate>20140912</indate>
<inno>6</inno>
<ondate/>
<onno/>
<latedate>20140912</latedate>
<sumno>6</sumno>
<status>1</status>
<level>12</level>
<size>.2</size>
<text>item c text </text>
</item>
<item name="D">
<name>D</name>
<indate/>
<inno/>
<ondate>20140712</ondate>
<onno>7</onno>
<latedate>20140712</latedate>
<sumno>7</sumno>
<status>1</status>
<level>13</level>
<size>.9</size>
<text>item d text </text>
</item>
</array>
</Items>
我使用此 xsl 进行分组,但无法添加和删除重复项
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:output method="xml" indent="yes"/>
<xsl:key name="items-by-id" match="item[@name]" use="name"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="array">
<xsl:copy>
<xsl:apply-templates select="item[@name][generate-id() = generate-id(key('items-by-id', name)[1])]" mode="group"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[@name]" mode="group">
<xsl:copy>
<xsl:copy-of select="name"/>
<xsl:apply-templates select="key('items-by-id', name)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[@name]">
<xsl:apply-templates select="node()[not(self::name)]"/>
</xsl:template>
</xsl:stylesheet>
我认为您的代码确实按 name
子元素对 item
元素进行了正确分组。您似乎还想消除重复的子元素,我不确定您是想仅通过元素名称还是通过元素名称和元素内容来消除重复的子元素。如果你想通过元素名称来完成,那么你可以定义第二个键 <xsl:key name="duplicated-elements" match="item/*" use="concat(../name, '|', local-name())"/>
。
至于添加空元素,你需要检查它们是否存在。
这是带有此类检查的样式表和第二个键:
<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="items-by-id" match="item[@name]" use="name"/>
<xsl:key name="duplicated-elements" match="item/*" use="concat(../name, '|', local-name())"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="array">
<xsl:copy>
<xsl:apply-templates select="item[@name][generate-id() = generate-id(key('items-by-id', name)[1])]" mode="group"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[@name]" mode="group">
<xsl:copy>
<xsl:variable name="current-group" select="key('items-by-id', name)"/>
<xsl:copy-of select="name"/>
<xsl:choose>
<xsl:when test="$current-group/indate">
<xsl:apply-templates select="$current-group/indate"/>
</xsl:when>
<xsl:otherwise>
<indate/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="$current-group/inno">
<xsl:apply-templates select="$current-group/inno"/>
</xsl:when>
<xsl:otherwise>
<inno/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="$current-group/ondate">
<xsl:apply-templates select="$current-group/ondate"/>
</xsl:when>
<xsl:otherwise>
<ondate/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="$current-group/onno">
<xsl:apply-templates select="$current-group/onno"/>
</xsl:when>
<xsl:otherwise>
<onno/>
</xsl:otherwise>
</xsl:choose>
<latedate>
<xsl:choose>
<xsl:when test="$current-group/indate > $current-group/ondate">
<xsl:value-of select="$current-group/indate"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$current-group/ondate"/>
</xsl:otherwise>
</xsl:choose>
</latedate>
<sumno>
<xsl:value-of select="sum($current-group/inno | $current-group/onno)"/>
</sumno>
<xsl:apply-templates select="key('items-by-id', name)/*[not(self::name | self::indate | self::inno | self::ondate | self::onno)][generate-id() = generate-id(key('duplicated-elements', concat(../name, '|', local-name()))[1])]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
还有一些问题,比如检查不存在的日期,但我希望你能解决它。