我是XSLT新手,我需要使用xslt将xml文件转换为另一个xml文件。
输入文件如下:
<root type="object">
<items type="array">
<item type="object">
<original_file_name type="string">filename-m.mp3</original_file_name>
<description type="string">some description text</description>
<created_at type="string">2017-02-20T20:52:52Z</created_at>
<metadata type="object">
<guest type="string">guestname here</guest>
<webInfo type="string">http://abc</webInfo>
<title type="string">title text testing</title>
<airDate type="string">2017-02-21</airDate>
</metadata>
<status type="string">live</status>
<asset_type type="string">video</asset_type>
<player_id type="string">391e099a718f4a62b44c78f97f85ecde</player_id>
<name type="string">title</name>
</item>
<item>
.....
</item>
</items>
</root>
需要将上述xml转换为以下格式:
<?xml version="1.0" encoding="utf-8"?>
<assets>
<item>
<original_file_name>filename-m.mp3</original_file_name>
<description>some description text</description>
<created_at>2017-02-20T20:52:52Z</created_at>
<guest>guestname here</guest>
<webInfo>http://abc</webInfo>
<title>title text testing</title>
<airDate>2017-02-21</airDate>
<status>live</status>
<asset_type>video</asset_type>
<player_id>391e099a718f4a62b44c78f97f85ecde</player_id>
<name>title</name>
</item>
<item>
.....
</item>
</assets>
转换规则如下:
1)将<root><items>...</items></root>
替换为<assets>...</assets>
2)删除所有属性
3)删除元数据标签,并将元数据的子节点带到item标签的子节点。
4)元数据标签的子节点是动态的,即子节点的数量和子节点的名称可能不同。
我能够解决前两点......第三和第四点的解决方案。 以下是我的代码:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<assets>
<xsl:for-each select="root/items/item">
<item>
<original_file_name>
<xsl:value-of select="original_file_name"/>
</original_file_name>
<description>
<xsl:value-of select="description"/>
</description>
</item>
</xsl:for-each>
</assets>
</xsl:template>
</xsl:stylesheet>
非常感谢您立即回复您发送的代码对我来说很好,但是当我们有以下行时,它会抛出错误。删除此行时,它可以正常工作。对于此行<xsl:strip-space elements="*" />
我收到以下错误无法从已加载的输入文档中删除空格。改为将输入文档作为XmlReader提供。
我还有一个疑问,如果我们想让一些子节点不是所有子节点(有选择地),该怎么办?
<root type="object">
<items type="array">
<item type="object">
<elem1></elem1>
<elem2></elem2>
<elem3></elem3>
<elem4></elem4>
<elem5></elem5>
<elem6></elem6>
<elem7></elem7>
</item>
</items>
</root>
输出应如下:
<assets>
<item>
<elem1></elem1>
<elem3></elem3>
<elem6></elem6>
<elem7></elem7>
</item>
</assets>
答案 0 :(得分:2)
在这样的问题中,从identity template
开始几乎总是最好的<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
这将按原样复制所有节点和元素,因此您只需要担心为需要更改的内容编写模板。
话虽如此,您需要删除属性,因此您实际上需要在此处更改身份模板以删除属性@*
的匹配,并将其移至单独的模板。
<xsl:template match="@*" />
要删除metadata
代码但保留其子代,请添加如此模板
<xsl:template match="metadata">
<xsl:apply-templates select="node()"/>
</xsl:template>
唯一的其他更改是将xsl:for-each
替换为xsl:apply-templates
,以允许其他模板完成其工作。
试试这个XSLT
<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:template match="/">
<assets>
<xsl:apply-templates select="root/items/item" />
</assets>
</xsl:template>
<xsl:template match="metadata">
<xsl:apply-templates select="node()"/>
</xsl:template>
<xsl:template match="@*" />
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)