2017-02-22 52 views
1

我是XSLT新手,我需要使用xslt将xml文件转换为另一个xml文件。初学XML到XML动态转换使用xslt

输入文件是如下:

<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

在类似这样的问题,它几乎总是最好先与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-eachxsl: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

了解如何使用模板匹配和应用模板:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

    <xsl:template match="node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="root"> 
     <assets> 
      <xsl:apply-templates/> 
     </assets> 
    </xsl:template> 

    <xsl:template match="items | metadata"> 
     <xsl:apply-templates/> 
    </xsl:template> 
</xsl:transform> 

在线http://xsltransform.net/bwdwsK

+0

非常感谢您的回复。 –