XSLT需求:将分组group节点移至data父节点并移除request节点
需求与解决方案
原始XML数据
<data> <request method="PUT"> <context> <record_count>5</record_count> <record_type>Customer</record_type> </context> <value> <company>ABC</company> <customer>Contoso</customer> </value> <value> <company>ABC</company> <customer>Forest</customer> </value> <value> <company>XYZ</company> <customer>Forest</customer> </value> <value> <company>XYZ</company> <customer>Cave</customer> </value> <value> <company>ABC</company> <customer>Cave</customer> </value> </request> </data>
现有XSLT转换代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="company-key" match="value" use="company"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:apply-templates /> </xsl:copy> </xsl:template> <xsl:template match="/data/request/value" /> <xsl:template match="/data/request/value[count(. | key('company-key', company)[1]) = 1]"> <xsl:element name="group"> <xsl:attribute name="company"> <xsl:value-of select="company"/> </xsl:attribute> <xsl:attribute name="method"> <xsl:value-of select="/data/request/@method"/> </xsl:attribute> <xsl:attribute name="record-type"> <xsl:value-of select="/data/request/context/record_type"/> </xsl:attribute> <xsl:for-each select="key('company-key', company)"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:for-each> </xsl:element> </xsl:template> </xsl:stylesheet>
现有转换输出
<data> <request method="PUT"> <context> <record_count>5</record_count> <record_type>Customer</record_type> </context> <group company="ABC" method="PUT" record-type="Customer"> <value> <company>ABC</company> <customer>Contoso</customer> </value> <value> <company>ABC</company> <customer>Forest</customer> </value> <value> <company>ABC</company> <customer>Cave</customer> </value> </group> <group company="XYZ" method="PUT" record-type="Customer"> <value> <company>XYZ</company> <customer>Forest</customer> </value> <value> <company>XYZ</company> <customer>Cave</customer> </value> </group> </request> </data>
期望输出
<data> <group company="ABC" method="PUT" record-type="Customer"> <value> <company>ABC</company> <customer>Contoso</customer> </value> <value> <company>ABC</company> <customer>Forest</customer> </value> <value> <company>ABC</company> <customer>Cave</customer> </value> </group> <group company="XYZ" method="PUT" record-type="Customer"> <value> <company>XYZ</company> <customer>Forest</customer> </value> <value> <company>XYZ</company> <customer>Cave</customer> </value> </group> </data>
修改后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 按company分组的键 --> <xsl:key name="company-key" match="value" use="company"/> <!-- 基础复制模板,默认复制节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <!-- 重写data节点的处理逻辑,直接生成包含group的data --> <xsl:template match="/data"> <data> <!-- 遍历每个分组的首个value节点,生成对应的group --> <xsl:for-each select="request/value[count(. | key('company-key', company)[1]) = 1]"> <group company="{company}" method="{/data/request/@method}" record-type="{/data/request/context/record_type}"> <!-- 复制当前分组下的所有value节点 --> <xsl:apply-templates select="key('company-key', company)"/> </group> </xsl:for-each> </data> </xsl:template> <!-- 直接移除整个request节点 --> <xsl:template match="/data/request"/> </xsl:stylesheet>
代码说明
- 重写
/data节点模板,直接在新生成的data节点内处理分组逻辑,让group直接成为data的子节点。 - 使用属性值模板(
{})简化group属性的赋值,代码更简洁直观。 - 添加匹配
/data/request的空模板,直接移除整个request节点及其内部未用到的内容。 - 保留基础复制模板,确保
value节点的内容能正常复制到group内部。
内容的提问来源于stack exchange,提问作者Paja
相关产品推荐
相关产品推荐

