我是XSLT的新手,我试图通过将以下元素值连接到属性来将输入xml转换为另一个。有没有办法用XSLT做到这一点?
输入xml:
<requests>
<request>
<name>BLA1</name>
<age>42</age>
</request>
<request>
<name>BLA2</name>
<age>24</age>
</request>
</requests>
结果xml:
<bodyParams>
<param name='name' value='BLA1,BLA2' />
<param name='age' value='42,24' />
</bodyParams>
提前感谢您的帮助!
答案 0 :(得分:2)
使用XSLT 2.0或3.0,您可以使用
<xsl:template match="requests">
<bodyParams>
<xsl:for-each-group select="request/*" group-by="node-name(.)">
<param name="{current-grouping-key()}" value="{string-join(current-group(), ',')}"/>
</xsl:for-each-group>
</bodyParams>
</xsl:template>
答案 1 :(得分:2)
这里有其他一些方法......
<xsl:template match="requests">
<xsl:variable name="name">
<xsl:value-of select="for $x in . return if ($x//name) then $x//name else ''" separator=","/>
</xsl:variable>
<xsl:variable name="age">
<xsl:value-of select="for $x in . return if ($x//age) then $x//age else ''" separator=","/>
</xsl:variable>
<bodyparams>
<param name="name" value="{$name}"/>
<param name="age" value="{$age}"/>
</bodyparams>
</xsl:template>
或
<xsl:template match="requests">
<xsl:variable name="name">
<xsl:value-of select="for $x in . return if ($x/request/*[1]) then $x/request/*[1] else ''" separator=","/>
</xsl:variable>
<xsl:variable name="age">
<xsl:value-of select="for $x in . return if ($x/request/*[2]) then $x/request/*[2] else ''" separator=","/>
</xsl:variable>
<bodyparams>
<param name="name" value="{$name}"/>
<param name="age" value="{$age}"/>
</bodyparams>
</xsl:template>
答案 2 :(得分:1)
以下是XSLT-1.0解决方案
param
的名称取自第一个name()
元素的子request
。 xsl:if
检查它是否是最后一个元素,如果不是,它会发出分隔符(XSLT-1.0中的分隔符)。
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/requests">
<bodyParams>
<xsl:for-each select="request[1]/*"> <!-- iterate over children's names of the first request element -->
<xsl:variable name="curPos" select="name()" /> <!-- remember its name -->
<xsl:element name="param"> <!-- construct <param name="..." value="..." /> element -->
<xsl:attribute name="name"><xsl:value-of select="name()" /></xsl:attribute>
<xsl:attribute name="value"><xsl:for-each select="//request/*[name()=$curPos]">
<xsl:value-of select="normalize-space(.)" /><xsl:if test="position() != last()"><xsl:text>,</xsl:text></xsl:if>
</xsl:for-each></xsl:attribute>
</xsl:element>
</xsl:for-each>
<xsl:apply-templates select="@*|node()" />
</bodyParams>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
答案 3 :(得分:1)
假设所有request
元素具有相同的子节点,顺序相同,我将在 XSLT 1.0 中解决此问题:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/requests">
<bodyParams>
<xsl:for-each select="request[1]/*">
<xsl:variable name="i" select="position()" />
<param name="{name()}">
<xsl:attribute name="value">
<xsl:for-each select="../../request/*[$i]">
<xsl:value-of select="." />
<xsl:if test="position()!=last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
</param>
</xsl:for-each>
</bodyParams>
</xsl:template>
</xsl:stylesheet>