处理XSLT中的元素和属性

时间:2012-12-07 09:00:09

标签: xml xslt

好的,所以我经历了很多相关的帖子,但未能找到问题的答案。我需要编写一个XSLT来以下列格式转换XML

<Message>
   <Receiver>
      <name>123</name>
      <address>111</address>
      <phone>1000</phone> 
   </Receiver>
   <List>
      <item>
         <no>1</no>
         <desc>one</desc>
      </item>
      <item>
         <no>2</no>
         <desc>two</desc>
      </item>
   </List>
<Message>

到此 -

<Message>    
   <Receiver name=123>
       <address>111</address>
       <phone>1000</phone> 
   </Receiver>
   <List>
       <item no=1>
          <desc>one</desc>
       </item>
       <item no=2>
          <desc>two</desc>
       </item>
   </List>
</Message>

我尝试过使用xsl模板匹配标记。 但是悲惨地失败了。任何想法或帮助非常感谢/

**注意我已编辑帖子以显示实际问题 - 我最初只发布了一部分以避免混淆,但似乎问题需要作为一个整体说明。抱歉给您带来不便。

1 个答案:

答案 0 :(得分:2)

这可以通过构建身份模板来完成。首先,您需要一个模板来匹配 Receiver 元素,复制它,但同时添加名称属性

<xsl:template match="Receiver">
    <Receiver name="{name}">
        <xsl:apply-templates select="@*|node()"/>
    </Receiver>
</xsl:template>

您可以为元素执行类似的操作。请注意这是如何使用“属性值模板”从name元素的值创建name属性。

然后,您只需要一个模板来匹配名称没有元素并忽略它们,因此不会输出它们。

<xsl:template match="name|no" />

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="Receiver">
        <Receiver name="{name}">
            <xsl:apply-templates select="@*|node()"/>
        </Receiver>
    </xsl:template>

    <xsl:template match="item">
        <item no="{no}">
            <xsl:apply-templates select="@*|node()"/>
        </item>
    </xsl:template>

    <xsl:template match="name|no" />

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

当应用于XML时,输出以下内容

<Message>
   <Receiver name="123">
      <address>111</address>
      <phone>1000</phone>
   </Receiver>
   <List>
      <item no="1">
         <desc>one</desc>
      </item>
      <item no="2">
         <desc>two</desc>
      </item>
  </List>
</Message>

现在,如果你想更通用,并且有一个规则将任何父元素的第一个'leaf'元素转换为属性,那么试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="*[*[1][not(*)]]">
        <xsl:copy>
            <xsl:attribute name="{name(*[1])}">
                <xsl:value-of select="*"/>
            </xsl:attribute>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*/*[1][not(*)]"/>

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

这也应该输出相同的结果。我会把它作为练习留给读者如何运作....