使用xslt进行初始XML到XML动态转换

时间:2017-02-22 08:56:39

标签: xml xslt

我是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>

2 个答案:

答案 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)

学习使用模板匹配和应用模板:

{{1}}

http://xsltransform.net/bwdwsK在线。