使用XSLT将一个XML转换为另一个XML

时间:2014-01-30 07:27:12

标签: xslt

你能帮我用xslt将xml转换成另一种格式吗?我有一个输入XML需要转换为另一种格式,但我尝试使用XSLT,但徒劳无功。请提供示例代码

以下是输入xml:

<?xml version="1.0" encoding="UTF-8"?>
<SyncApp xsi:schemaLocation="http://www.xyz.com/app/1_0 Application_1_0.xsd" xmlns="http://www.xyz.com/app/1_0" xmlns:env="http://www.xyz.com/group/common/1_0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:AppArea>
    <env:Sender>
        <env:LogicalID>String</env:LogicalID>
    </env:Sender>
    <env:Receiver>
        <env:LogicalID>String</env:LogicalID>
    </env:Receiver>
    <env:CreationDateTime>2001-12-17T09:30:47Z</env:CreationDateTime>
    <env:BODID>String</env:BODID>
    <env:UserArea>
        <env:BooleanValue name="String">true</env:BooleanValue>
    </env:UserArea>
</env:AppArea>
<Data>
    <Sync>
        <env:ActionCriteria>String</env:ActionCriteria>
        <env:UserArea>
            <env:BooleanValue name="String">true</env:BooleanValue>
        </env:UserArea>
    </Sync>
    <App>
        <ID>1234</ID>
        <NameShort>Test2</NameShort>
        <NameLong>Test1</NameLong>
        <Description>Test</Description>
        <UserArea>
            <env:BooleanValue name="String">true</env:BooleanValue>
            <env:DateTimeValue name="String">2001-12-17T09:30:47Z</env:DateTimeValue>
        </UserArea>
    </App>
</Data>
</SyncApp>

输出应该是:

<?xml version="1.0" encoding="UTF-8"?>
<SyncApp>
<App Name="Test2" TypeNum="6" MDIDTest="1234">
  <AttrDef Name="MDID">
     <AttrValue Value="1234"/>
  </AttrDef>
  <AttrDef Name="LongName">
     <AttrValue Value="Test1"/>
  </AttrDef>
  <AttrDef Name="Description">
     <AttrValue Value="Test"/>
  </AttrDef>
</App>
</SyncApp>

请找到XSLT代码:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="/">
    <SynchFromXtoY>
        <xsl:apply-templates select="SyncApp"/>
    </SynchFromXtoY>
</xsl:template>
<xsl:template match="SyncApp">
    <xsl:apply-templates select="Data"/>
</xsl:template> 
<xsl:template match="Data">
    <xsl:apply-templates select="App"/>
</xsl:template>
<xsl:template match="App">
<App>
    <xsl:attribute name="Name">
        <xsl:value-of select="NameShort"/>
    </xsl:attribute>
    <xsl:attribute name="TypeNum">
        <xsl:value-of select="'6'"/>
    </xsl:attribute>        
    <xsl:attribute name="MDIDTest">
        <xsl:value-of select="MDID"/>
    </xsl:attribute>
    <AttrDef>
       <xsl:attribute name="Name">
        <xsl:value-of select="'MDID'"/>
       </xsl:attribute>
       <AttrValue>
         <xsl:attribute name="Value">
         <xsl:value-of select="MDID"/>
        </xsl:attribute>
       </AttrValue>
    </AttrDef>
    <AttrDef>
       <xsl:attribute name="Name">
        <xsl:value-of select="'LongName'"/>
       </xsl:attribute>
       <AttrValue>
         <xsl:attribute name="Value">
         <xsl:value-of select="NameLong"/>
        </xsl:attribute>
       </AttrValue>
    </AttrDef>
    <AttrDef>
       <xsl:attribute name="Name">
        <xsl:value-of select="'Description'"/>
       </xsl:attribute>
       <AttrValue>
         <xsl:attribute name="Value">
         <xsl:value-of select="Description"/>
        </xsl:attribute>
       </AttrValue>
    </AttrDef>
  </App>
 </xsl:template>
</xsl:stylesheet>

提前致谢。

BR / SRINIVAS。

1 个答案:

答案 0 :(得分:2)

你的解决方案实际上并不遥远。您遇到的问题主要是命名空间。在你的XML中你有这个代码......

<SyncApp xmlns="http://www.xyz.com/app/1_0" ....

这是默认命名空间的声明,这意味着XML中没有前缀的任何元素(如“SyncApp”本身,“数据”和“应用”)都属于此默认命名空间。

但是,在您的XSLT中根本没有提到这个命名空间。这意味着当你这样做时......

<xsl:template match="SyncApp">

这是在寻找一个名为“SyncApp”的元素,它不在命名空间中。这是一个名为“SyncApp”的元素,它属于命名空间。命名空间实际上是元素名称的一部分。

你需要做的是在XSLT中声明命名空间,就像这样(你使用的前缀可以是任何东西,它是必须匹配的URI)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                 xmlns:app="http://www.xyz.com/app/1_0"

然后,在您引用XML中的元素的任何xpath表达式中,必须在它们前面添加名称空间前缀

<xsl:template match="app:SyncApp">

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:app="http://www.xyz.com/app/1_0"
     xmlns:env="http://www.xyz.com/group/common/1_0"
     exclude-result-prefixes="app env">

<xsl:output indent="yes" method="xml"/>

<xsl:template match="/">
    <SynchFromXtoY>
        <xsl:apply-templates select="app:SyncApp"/>
    </SynchFromXtoY>
</xsl:template>

<xsl:template match="app:SyncApp">
    <xsl:apply-templates select="app:Data"/>
</xsl:template> 

<xsl:template match="app:Data">
    <xsl:apply-templates select="app:App"/>
</xsl:template>

<xsl:template match="app:App">
 <App Name="{app:NameShort}" TypeNum="6" MDIDTest="{app:MDID}">
    <AttrDef Name="MDID">
       <AttrValue Value="{app:MDID}" />
    </AttrDef>
    <AttrDef Name="LongName">
       <AttrValue Value="{app:NameLong}" />
    </AttrDef>
    <AttrDef Name="Description">
       <AttrValue Value="{app:Description}" />
    </AttrDef>
  </App>
 </xsl:template>
</xsl:stylesheet>

请注意这里使用属性值模板来简化XSLT。而不是写这个

   <AttrValue>
     <xsl:attribute name="Value">
       <xsl:value-of select="app:Description"/>
     </xsl:attribute>
   </AttrValue>

你可以写这个......

<AttrValue Value="{app:Description}" />

花括号表示要计算的表达式,而不是字面输出。