sam*_*ude 1 xml xslt merge xslt-2.0
我有一个XML文件authors.xml如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<authors>
<author>
<name>Leonardo da Vinci</name>
<nationality>Italian</nationality>
</author>
<author>
<name>Pablo Picasso</name>
<nationality>Spanish</nationality>
</author>
</authors>
Run Code Online (Sandbox Code Playgroud)
和另一个文件列出他们的艺术品artwork.xml如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<artworks>
<artwork>
<title>Mona Lisa</title>
<author>Leonardo da Vinci</author>
<date>1497</date>
<form>painting</form>
</artwork>
<artwork>
<title>Vitruvian Man</title>
<author>Leonardo da Vinci</author>
<date>1499</date>
<form>painting</form>
</artwork>
<artwork>
<title>Absinthe Drinker</title>
<author>Pablo Picasso</author>
<date>1479</date>
<form>painting</form>
</artwork>
<artwork>
<title>Chicago Picasso</title>
<author>Pablo Picasso</author>
<date>1950</date>
<form>sculpture</form>
</artwork>
</artworks>
Run Code Online (Sandbox Code Playgroud)
我想要做的是将这两个XML文件合并到另一个处理过的XML文件中.XSLT将列出所有作者,并在其中列出与该特定作者相关的所有艺术作品,并按艺术作品形式对其进行分组.XSLT还将计算图稿组的数量.组的持续时间也作为元素属性添加.这在下面的XML文件中进一步说明:
<?xml version="1.0" encoding="UTF-8" ?>
<authors>
<author>
<name>Leonardo da Vinci</name>
<nationality>Italian</nationality>
<artworks form="painting" duration="1497-1499" quantity="2">
<artwork date="1497">
<title>Mona Lisa</title>
</artwork>
<artwork date="1499">
<title>Vitruvian Man</title>
</artwork>
</artworks>
</author>
<author>
<name>Pablo Picasso</name>
<nationality>Spanish</nationality>
<artworks form="painting" duration="1479-1479" quantity="1">
<artwork date="1479">
<title>Absinthe Drinker</title>
</artwork>
</artworks>
<artworks form="sculpture" duration="1950-1950" quantity="1">
<artwork date="1950">
<title>Chicago Picasso</title>
</artwork>
</artworks>
</author>
</authors>
Run Code Online (Sandbox Code Playgroud)
我还是新手.我设法做的是获取所有作者的部分,现在我不确定如何从其他XML文件中提取数据,同时还要计算艺术品的出现等等.我在程序编程方面非常有经验,比如C或C++,但这种声明式编程方法真的让我头脑发热!希望有人可以指出我正确的方向,以便我能做到这一点.
此样式表将生成您期望的输出,使用该authors.xml
文件作为输入源,并具有artworks.xml
在同一目录中:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:variable name="artworks" select="doc('artworks.xml')/artworks"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="authors/author">
<xsl:copy>
<xsl:copy-of select="name"/>
<xsl:copy-of select="nationality"/>
<xsl:for-each-group
select="$artworks/artwork[author=current()/name]"
group-by="form">
<artworks form="{form}"
duration="{min(current-group()/date)}-{max(current-group()/date)}"
quantity="{count(current-group())}">
<xsl:apply-templates select="current-group()"/>
</artworks>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="artwork">
<artwork date="{date}">
<title><xsl:value-of select="title"/></title>
</artwork>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
以下是对上述代码的解释:
我使用a xsl:variable
来引用artworks
导入文档中的子树:
<xsl:variable name="artworks" select="doc('artworks.xml')/artworks"/>
Run Code Online (Sandbox Code Playgroud)
此模板是一个标识转换,它将匹配任何节点和属性并将其复制到输出.它的优先级低于其他两个模板,因此只有在其他模板不匹配时才会调用它:
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
第二个模板必须匹配authors/author
(而不是author
,因为在处理两个文档时都会调用它,并且author
内部还有另一个模板artwork
).该copy-of
元素复制所选节点的整个子树(元素,内容和属性).
<xsl:template match="authors/author">
<xsl:copy>
<xsl:copy-of select="name"/>
<xsl:copy-of select="nationality"/>
...
</xsl:copy>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
在for-each-group
每个迭代上artwork
从元件artworks.xml
文件具有相同name
的author
从输入文档中的当前节点的元素(authors.xml
).它被分组form
.您可以参考当前组,使用current-group()
它来计算max
和min
日期,计算数量和打印<artwork>
节点.
<xsl:for-each-group
select="$artworks/artwork[author=current()/name]"
group-by="form">
<artworks form="{form}"
duration="{min(current-group()/date)}-{max(current-group()/date)}"
quantity="{count(current-group())}">
<xsl:apply-templates select="current-group()"/>
</artworks>
</xsl:for-each-group>
Run Code Online (Sandbox Code Playgroud)
最后,此模板格式化每个artwork
节点:
<xsl:template match="artwork">
<artwork date="{date}">
<title><xsl:value-of select="title"/></title>
</artwork>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
您可以在单个根/
匹配模板和几个嵌套for-each
块中以不同的方式完成所有这些操作,但在XSLT中进行编码时,使用模板是一种更好的做法.
归档时间: |
|
查看次数: |
1683 次 |
最近记录: |