XML文件转换
问题描述:
artworks.xml文件:XML文件转换
<artworks>
<artwork>
<title>Adoration of the Magi</title>
<author>GHIRLANDAIO, Domenico</author>
<date>1487</date>
<technique>Tempera on wood, diameter: 171 cm</technique>
<location>Galleria degli Uffizi, Florence</location>
<form>painting</form>
<type>religious</type>
</artwork>
</artworks>
author.xml文件:
<authors>
<author>
<name>AMADEO, Giovanni Antonio</name>
<born-died>b. ca. 1447, Pavia, d. 1522, Milano</born-died>
<nationality>Italian</nationality>
<biography>Giovanni Antonio Amadeo was an Italian early Renaissance sculptor</biography>
</author>
<authors>
的Output.xml文件:
<authors>
<author>
<name>AMADEO, Giovanni Antonio</name>
<born-died>b. ca. 1447, Pavia, d. 1522, Milano</born-died>
<nationality>Italian</nationality>
<biography>Giovanni Antonio Amadeo was an Italian early Renaissance sculptor</biography>
<artworks form="architecture">
<artwork date="1473">
<title>Faهade of the church</title>
<technique>Marble</technique>
<location>Certosa, Pavia</location>
</artwork>
</artworks>
</author>
</authors>
的artworks.xml作者作品是一个外键,引用authors.xml作者 条目。
我想合并这两个XML文档并创建一个新的XML文件,其中 应为每个作者存储以下信息:名称,出生死亡,国籍, 传记和所有作品。艺术品按表格分组,然后按日期排序。对于 每个艺术品,标题,技术和位置存储
是challanging:)
答
我得到尽可能使用document()功能您的问题的合流部分:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" />
<xsl:template match="authors">
<authors>
<xsl:for-each select="author">
<author>
<xsl:copy-of select="name" />
<xsl:copy-of select="born-died" />
<xsl:copy-of select="nationality" />
<xsl:copy-of select="biography" />
<xsl:variable name="name" select="name" />
<artworks>
<xsl:for-each select="document('artworks.xml')//artwork[author=$name]">
<artwork>
<xsl:copy-of select="title" />
<xsl:copy-of select="date" />
<xsl:copy-of select="technique" />
<xsl:copy-of select="location" />
<xsl:copy-of select="form" />
<xsl:copy-of select="type" />
</artwork>
</xsl:for-each>
</artworks>
</author>
</xsl:for-each>
</authors>
</xsl:template>
</xsl:stylesheet>
我使用Intel's XSLT command line tool进行转换。这里的命令行:
soaexslt2.exe merge.xsl authors.xml output.xml
答
这是诀窍。它显示了许多有用的XSLT技术 - 延伸的恒等变换,Muenchian分组的,使用document()
到从辅助文件中的数据合并,抑制空元素的输出 - 这使得它值得在满工作了:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="authors"
select="document('authors.xml')/authors/author"/>
<xsl:variable name="artworks"
select="/artworks/artwork"/>
<!-- use Muenchian grouping to create a list of all distinct form values -->
<xsl:key name="form-key"
match="/artworks/artwork/form"
use="."/>
<xsl:variable name="forms"
select="/artworks/artwork/form[generate-id(.) = generate-id(key('form-key', .)[1])]"/>
<xsl:template match="/">
<authors>
<xsl:apply-templates select="$authors"/>
</authors>
</xsl:template>
<xsl:template match="author">
<xsl:variable name="artworks-for-author"
select="$artworks[author=current()/name]"/>
<!-- only create an author element if it will contain at least one artwork -->
<xsl:if test="$artworks-for-author">
<author>
<xsl:apply-templates select="name|born-died|nationality|biography"/>
<xsl:for-each select="$forms">
<!-- only create an artworks element if there's at least one artwork with this form -->
<xsl:variable name="artworks-with-form"
select="$artworks-for-author[form=current()]"/>
<xsl:if test="$artworks-with-form">
<artworks form="{current()}">
<xsl:apply-templates select="$artworks-with-form">
<xsl:sort select="date"/>
</xsl:apply-templates>
</artworks>
</xsl:if>
</xsl:for-each>
</author>
</xsl:if>
</xsl:template>
<xsl:template match="artwork">
<xsl:apply-templates select="title|technique|location"/>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答
甲完整的解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="authors" select="document('author.xml')" />
<xsl:variable name="artworks" select="/artworks/artwork" />
<xsl:key name="byNameForm" match="artworks/artwork"
use="concat(author, '|', form)" />
<xsl:template match="/">
<authors>
<xsl:apply-templates select="$authors/*/author" />
</authors>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="author">
<author>
<xsl:apply-templates />
<xsl:apply-templates select="$artworks[author=current()/name]" />
</author>
</xsl:template>
<xsl:template match="artworks/artwork" />
<xsl:template match="artworks/artwork[generate-id()=
generate-id(key('byNameForm', concat(author, '|', form))[1])]">
<artworks form="{form}">
<xsl:apply-templates
select="key('byNameForm', concat(author, '|', form))"
mode="form">
<xsl:sort select="date" data-type="number" />
</xsl:apply-templates>
</artworks>
</xsl:template>
<xsl:template match="artworks/artwork" mode="form">
<artwork date="{date}">
<xsl:apply-templates select="title|technique|location" />
</artwork>
</xsl:template>
</xsl:stylesheet>
输入:
<artworks>
<artwork>
<title>Adoration of the Magi</title>
<author>GHIRLANDAIO, Domenico</author>
<date>1486</date>
<technique>Tempera on wood, diameter: 171 cm</technique>
<location>Galleria degli Uffizi, Florence</location>
<form>painting</form>
<type>religious</type>
</artwork>
<artwork>
<title>Something</title>
<author>AMADEO, Giovanni Antonio</author>
<date>1484</date>
<technique>Marble</technique>
<location>Mars</location>
<form>sculpture</form>
<type>religious</type>
</artwork>
<artwork>
<title>Something2</title>
<author>AMADEO, Giovanni Antonio</author>
<date>1487</date>
<technique>Glue</technique>
<location>New York</location>
<form>sculpture</form>
<type>secular</type>
</artwork>
<artwork>
<title>Something3</title>
<author>AMADEO, Giovanni Antonio</author>
<date>1482</date>
<technique>Some tech</technique>
<location>Mars</location>
<form>paper</form>
<type>religious</type>
</artwork>
</artworks>
和:
<authors>
<author>
<name>AMADEO, Giovanni Antonio</name>
<born-died>b. ca. 1447, Pavia, d. 1522, Milano</born-died>
<nationality>Italian</nationality>
<biography>Giovanni Antonio Amadeo was an Italian early
Renaissance sculptor</biography>
</author>
<author>
<name>GHIRLANDAIO, Domenico</name>
<born-died>b. ca. 1447, Pavia, d. 1522, Venice</born-died>
<nationality>Italian</nationality>
<biography>N/A</biography>
</author>
</authors>
输出:
<authors>
<author>
<name>AMADEO, Giovanni Antonio</name>
<born-died>b. ca. 1447, Pavia, d. 1522, Milano</born-died>
<nationality>Italian</nationality>
<biography>Giovanni Antonio Amadeo was an Italian early
Renaissance sculptor</biography>
<artworks form="sculpture">
<artwork date="1484">
<title>Something</title>
<technique>Marble</technique>
<location>Mars</location>
</artwork>
<artwork date="1487">
<title>Something2</title>
<technique>Glue</technique>
<location>New York</location>
</artwork>
</artworks>
<artworks form="paper">
<artwork date="1482">
<title>Something3</title>
<technique>Some tech</technique>
<location>Mars</location>
</artwork>
</artworks>
</author>
<author>
<name>GHIRLANDAIO, Domenico</name>
<born-died>b. ca. 1447, Pavia, d. 1522, Venice</born-died>
<nationality>Italian</nationality>
<biography>N/A</biography>
<artworks form="painting">
<artwork date="1486">
<title>Adoration of the Magi</title>
<technique>Tempera on wood, diameter: 171 cm</technique>
<location>Galleria degli Uffizi, Florence</location>
</artwork>
</artworks>
</author>
</authors>
编辑:更新由作者来驱动的处理,所以,即使作者没有任何作品将包括在内。
+1非常好的答案:遍历作者和按作者+表格分组作品。一些未成年人:如果您要覆盖身份规则,请使用' '而不是' '如果你打算使用push风格,你可以像'select ='一样完成它$ ART [generate-id()= generate-id(key('byNameForm',concat(current()/name,'|',form))[1])]''或者您可以为作者使用第二个键(这将在外部文档上添加键的示例)。 –
2011-04-25 19:49:52