0

好的,所以我浏览了许多相关的帖子,但无法确定我的问题的答案。我需要编写一个 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 模板匹配标签。但失败得很惨。非常感谢任何想法或帮助/

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

4

1 回答 1

2

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

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

您可以对item元素执行类似的操作。请注意这是如何利用“属性值模板”从名称元素的值创建名称属性的。

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

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

现在,如果您想要更通用,并且有一个规则,将任何父元素的第一个“叶子”元素转换为属性,那么试试这个 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>

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

于 2012-12-07T09:12:40.080 回答