在 <xsl:for-each>
的上下文中,我必须从 XML 文档中仅选择唯一记录环形。我受 Visual Studio 限制只能使用 XSL 1.0。
<availList>
<item>
<schDate>2010-06-24</schDate>
<schFrmTime>10:00:00</schFrmTime>
<schToTime>13:00:00</schToTime>
<variousOtherElements></variousOtherElements>
</item>
<item>
<schDate>2010-06-24</schDate>
<schFrmTime>10:00:00</schFrmTime>
<schToTime>13:00:00</schToTime>
<variousOtherElements></variousOtherElements>
</item>
<item>
<schDate>2010-06-25</schDate>
<schFrmTime>10:00:00</schFrmTime>
<schToTime>12:00:00</schToTime>
<variousOtherElements></variousOtherElements>
</item>
<item>
<schDate>2010-06-26</schDate>
<schFrmTime>13:00:00</schFrmTime>
<schToTime>14:00:00</schToTime>
<variousOtherElements></variousOtherElements>
</item>
<item>
<schDate>2010-06-26</schDate>
<schFrmTime>10:00:00</schFrmTime>
<schToTime>12:00:00</schToTime>
<variousOtherElements></variousOtherElements>
</item>
</availList>
唯一性必须基于三个子元素的值:schDate
, schFrmTime
和 schToTime
.如果两个item
元素的所有三个子元素都具有相同的值,它们是重复的。在上面的 XML 中,第一项和第二项是重复项。其余的都是独一无二的。如上所述,每个项目都包含我们不希望包含在比较中的其他元素。 “独特性”应该是这三个要素的一个因素,并且是单独的一个因素。
我试图通过以下方式实现这一目标:
availList/item[not(schDate = preceding:: schDate and schFrmTime = preceding:: schFrmTime and schToTime = preceding:: schToTime)]
这背后的想法是选择没有前面元素具有相同 schDate
的记录, schFrmTime
和 schToTime
.但是,它的输出缺少最后一项。这是因为我的 XPath 实际上排除了在整个前面的文档中匹配所有子元素值 的项目。无单item
匹配最后一个项目的所有子元素 - 但因为每个元素的值都单独存在于另一个项目中,所以最后一个项目被排除在外。
通过将所有子值作为串联字符串与前面每个项目的相同串联值进行比较,我可以获得正确的结果。有人知道我可以做到这一点的方法吗?
最佳答案
我。作为单个 XPath 表达式:
/*/item[normalize-space() and not(. = preceding-sibling::item)]
二。更高效的 (XSLT) 实现,使用键:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kItemByVal" match="item" use="."/>
<xsl:template match="/">
<xsl:copy-of select=
"*/item[generate-id() = generate-id(key('kItemByVal', .))]
"/>
</xsl:template>
</xsl:stylesheet>
I 和 II,当应用于提供的 XML 文档时,正确选择/复制以下节点:
<item><schDate>2010-06-24</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>13:00:00</schToTime></item>
<item><schDate>2010-06-25</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>12:00:00</schToTime></item>
<item><schDate>2010-06-26</schDate><schFrmTime>13:00:00</schFrmTime><schToTime>14:00:00</schToTime></item>
<item><schDate>2010-06-26</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>12:00:00</schToTime></item>
更新:以防<item>
有其他 child ,那么这个变换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kItemBy3Children" match="item"
use="concat(schDate, '+', schFrmTime, '+', schToTime)"/>
<xsl:template match="/">
<xsl:copy-of select=
"*/item[generate-id()
= generate-id(key('kItemBy3Children',
concat(schDate,
'+', schFrmTime,
'+', schToTime)
)
)
]
"/>
</xsl:template>
</xsl:stylesheet>
产生想要的结果。
关于xml - 在 XSLT/XPath 中选择唯一记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3016929/