这可以通过建立在身份模板上来完成。首先你需要一个模板来匹配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>
这也应该输出相同的结果。我将把它作为练习留给读者它是如何工作的......