Xml 不同元素和分组
给定以下xml片段:Xml 不同元素和分组,xml,xslt,xpath,Xml,Xslt,Xpath,给定以下xml片段: <Problems> <Problem> <File>file1</File> <Description>desc1</Description> </Problem> <Problem> <File>file1</File> <Description>desc2</Description>
<Problems>
<Problem>
<File>file1</File>
<Description>desc1</Description>
</Problem>
<Problem>
<File>file1</File>
<Description>desc2</Description>
</Problem>
<Problem>
<File>file2</File>
<Description>desc1</Description>
</Problem>
</Problems>
文件1
描述1
文件1
描述2
文件2
描述1
我需要制作一些类似的东西
<html>
<body>
<h1>file1</h1>
<p>des1</p>
<p>desc2</p>
<h1>file2</h1>
<p>des1</p>
</body>
</html>
文件1
des1
描述2
文件2
des1
我试着用钥匙,比如
<xsl:key name="files" match="Problem" use="File"/>
但我真的不明白如何进行下一步,或者这是否是正确的方法 下面是我将如何使用Muenchean方法来实现这一点。谷歌“xslt muenchean”从更聪明的人那里获取更多信息。也许有一个聪明的方法,但我会把它留给其他人 注意,我避免在xml元素名称的开头使用大写字母,例如“File”,但这取决于您
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:key name="files" match="/Problems/Problem/File" use="./text()"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="Problems"/>
</body>
</html>
</xsl:template>
<xsl:template match="Problems">
<xsl:for-each select="Problem/File[generate-id(.) = generate-id(key('files', .))]">
<xsl:sort select="."/>
<h1>
<xsl:value-of select="."/>
</h1>
<xsl:apply-templates select="../../Problem[File=current()/text()]"/>
</xsl:for-each>
</xsl:template>
<xsl:template match="Problem">
<p>
<xsl:value-of select="Description/text()"/>
</p>
</xsl:template>
</xsl:stylesheet>
其思想是,使用每个文件元素的文本值为其设置关键帧。然后,仅当文件值与已设置关键帧的元素相同时才显示文件值。要检查它们是否相同,请使用generate-id。有一种类似的方法,比较匹配的第一个元素。我不能告诉你哪个更有效
我已经在这里使用Marrowsoft Xselerator(我最喜欢的xslt工具)对代码进行了测试,虽然现在不再可用,但它是afaik。我得到的结果是:
<html>
<body>
<h1>file1</h1>
<p>desc1</p>
<p>desc2</p>
<h1>file2</h1>
<p>desc1</p>
</body>
</html>
文件1
描述1
描述2
文件2
描述1
这是在使用msxml4
我已按文件对输出进行了排序。我不确定你是否想要那样
我希望这会有所帮助。与Richard提出的解决方案相比,该解决方案更简单、更高效,同时也更通用 此转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- -->
<xsl:key name="kFileByVal" match="File"
use="." />
<!-- -->
<xsl:key name="kDescByFile" match="Description"
use="../File"/>
<!-- -->
<xsl:template match="/*">
<html>
<body>
<xsl:for-each select=
"*/File[generate-id()
=
generate-id(key('kFileByVal',.)[1])]">
<h1><xsl:value-of select="."/></h1>
<xsl:for-each select="key('kDescByFile', .)">
<p><xsl:value-of select="."/></p>
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
<Problems>
<Problem>
<File>file1</File>
<Description>desc1</Description>
</Problem>
<Problem>
<File>file1</File>
<Description>desc2</Description>
</Problem>
<Problem>
<File>file2</File>
<Description>desc1</Description>
</Problem>
</Problems>
<html>
<body>
<h1>file1</h1>
<p>desc1</p>
<p>desc2</p>
<h1>file2</h1>
<p>desc1</p>
</body>
</html>
应用于提供的XML文档时:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- -->
<xsl:key name="kFileByVal" match="File"
use="." />
<!-- -->
<xsl:key name="kDescByFile" match="Description"
use="../File"/>
<!-- -->
<xsl:template match="/*">
<html>
<body>
<xsl:for-each select=
"*/File[generate-id()
=
generate-id(key('kFileByVal',.)[1])]">
<h1><xsl:value-of select="."/></h1>
<xsl:for-each select="key('kDescByFile', .)">
<p><xsl:value-of select="."/></p>
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
<Problems>
<Problem>
<File>file1</File>
<Description>desc1</Description>
</Problem>
<Problem>
<File>file1</File>
<Description>desc2</Description>
</Problem>
<Problem>
<File>file2</File>
<Description>desc1</Description>
</Problem>
</Problems>
<html>
<body>
<h1>file1</h1>
<p>desc1</p>
<p>desc2</p>
<h1>file2</h1>
<p>desc1</p>
</body>
</html>
文件1
描述1
文件1
描述2
文件2
描述1
产生想要的结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- -->
<xsl:key name="kFileByVal" match="File"
use="." />
<!-- -->
<xsl:key name="kDescByFile" match="Description"
use="../File"/>
<!-- -->
<xsl:template match="/*">
<html>
<body>
<xsl:for-each select=
"*/File[generate-id()
=
generate-id(key('kFileByVal',.)[1])]">
<h1><xsl:value-of select="."/></h1>
<xsl:for-each select="key('kDescByFile', .)">
<p><xsl:value-of select="."/></p>
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
<Problems>
<Problem>
<File>file1</File>
<Description>desc1</Description>
</Problem>
<Problem>
<File>file1</File>
<Description>desc2</Description>
</Problem>
<Problem>
<File>file2</File>
<Description>desc1</Description>
</Problem>
</Problems>
<html>
<body>
<h1>file1</h1>
<p>desc1</p>
<p>desc2</p>
<h1>file2</h1>
<p>desc1</p>
</body>
</html>
文件1
描述1
描述2
文件2
描述1
请注意第一个元素的简单匹配模式,以及如何使用第二个
,找到具有给定值的“文件
”元素同级的所有“描述
”元素
我们本可以使用更多的模板来代替拉式处理,但是这是一个非常简单的案例,而且解决方案确实受益于更短、更紧凑和更可读的代码
另请注意,在一个示例中,通常会使用指令而不是。这XSLT 1.0解决方案也会起作用。比其他解决方案更简洁
<xsl:template match="/">
<html><body>
<xsl:for-each select="//File[not(.=preceding::*)]">
<h1><xsl:value-of select="." /></h1>
<xsl:for-each select="//Problem[File=current()]/Description">
<p><xsl:value-of select="." /></p>
</xsl:for-each>
</xsl:for-each>
</body></html>
</xsl:template>
结果:
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h1>file1</h1>
<p>desc1</p>
<p>desc2</p>
<h1>file2</h1>
<p>desc1</p>
</body>
</html>
文件1
描述1
描述2
文件2
描述1
干杯。我甚至没有注意到你是澳大利亚人,否则我会使用更多的口语@rjonston:我提供了一个比Richards更干净、更高效的解决方案。@Dimitre。我只使用过Muenchean分组的键。感谢您以更广泛的方式使用它们。另外,我还没有看过XSLT2.0,所以为每个组编写的代码也很有趣。干杯,新年快乐。@Richard:祝你新年快乐,Richard。