我有一个XML需要转换为更好的项目分组。
优选XSLT 1.0
这可能吗?
我需要离开这个:
<table name = "dogs">
<fields>
<field name = "name" value = "dog1"></field>
<field name = "age" value = "2"></field>
<field name = "haircolor" value = "brown"></field>
<field name = "name" value = "dog2"></field>
<field name = "age" value = "10"></field>
<field name = "haircolor" value = "white"></field>
<field name = "name" value = "dog3"></field>
<field name = "age" value = "7"></field>
<field name = "haircolor" value = "black"></field>
<field name = "name" value = "dog4"></field>
<field name = "age" value = "4"></field>
<field name = "haircolor" value = "brown"></field>
</fields>
</table>
对此:
<dogs count = "4">
<dog>
<name>dog1</name>
<age>2</age>
<haircolor>brown</haircolor>
</dog>
<dog>
<name>dog2</name>
<age>10</age>
<haircolor>white</haircolor>
</dog>
<dog>
<name>dog3</name>
<age>7</age>
<haircolor>black</haircolor>
</dog>
<dog>
<name>dog4</name>
<age>4</age>
<haircolor>brown</haircolor>
</dog>
</dogs>
答案 0 :(得分:1)
这是一种XSLT 1.0方法:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="table">
<xsl:element name="{@name}">
<xsl:variable name="fields" select="fields/field[@name = current()/fields/field[1]/@name]"/>
<xsl:attribute name="count"><xsl:value-of select="count($fields)"/></xsl:attribute>
<xsl:apply-templates select="$fields"/>
</xsl:element>
</xsl:template>
<xsl:template match="field">
<xsl:variable name="this" select="."/>
<xsl:element name="{../../@name}">
<name><xsl:value-of select="@value"/></name>
<xsl:apply-templates select="following-sibling::field[1][not(@name = $this/@name)]" mode="trans">
<xsl:with-param name="head-name" select="$this/@name"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="field" mode="trans">
<xsl:param name="head-name"/>
<xsl:element name="{@name}"><xsl:value-of select="@value"/></xsl:element>
<xsl:apply-templates select="following-sibling::field[1][not(@name = $head-name)]" mode="trans">
<xsl:with-param name="head-name" select="$head-name"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
如果您想使用参数,那么代码可以使用
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="head-name" select="'name'"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="table">
<xsl:element name="{@name}">
<xsl:variable name="fields" select="fields/field[@name = $head-name]"/>
<xsl:attribute name="count"><xsl:value-of select="count($fields)"/></xsl:attribute>
<xsl:apply-templates select="$fields"/>
</xsl:element>
</xsl:template>
<xsl:template match="field">
<xsl:variable name="this" select="."/>
<xsl:element name="{../../@name}">
<name><xsl:value-of select="@value"/></name>
<xsl:apply-templates select="following-sibling::field[1][not(@name = $head-name)]" mode="trans"/>
</xsl:element>
</xsl:template>
<xsl:template match="field" mode="trans">
<xsl:element name="{@name}"><xsl:value-of select="@value"/></xsl:element>
<xsl:apply-templates select="following-sibling::field[1][not(@name = $head-name)]" mode="trans">
<xsl:with-param name="head-name" select="$head-name"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
假设每组字段都以名称开头:
XSLT 1.0
<?xml version="1.0" encoding="UTF-8"?>
<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:key name="fields-by-lead" match="field[@name!='name']" use="generate-id(preceding-sibling::field[@name='name'][1])" />
<xsl:template match="/table">
<xsl:variable name="names" select="fields/field[@name='name']" />
<dogs count="{count($names)}">
<xsl:for-each select="$names">
<dog>
<name><xsl:value-of select="@value"/></name>
<xsl:for-each select="key('fields-by-lead', generate-id())">
<xsl:element name="{@name}">
<xsl:value-of select="@value"/>
</xsl:element>
</xsl:for-each>
</dog>
</xsl:for-each>
</dogs>
</xsl:template>
</xsl:stylesheet>
以下修改为名称与第一个字段名称匹配的每个字段开始一个新组。
XSLT 1.0
<?xml version="1.0" encoding="UTF-8"?>
<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:key name="fields-by-lead" match="field" use="generate-id(preceding-sibling::field[@name=/table/fields/field[1]/@name][1])" />
<xsl:template match="/table">
<xsl:variable name="lead-label" select="/table/fields/field[1]/@name" />
<xsl:variable name="leads" select="fields/field[@name=$lead-label]" />
<dogs count="{count($leads)}">
<xsl:for-each select="$leads">
<dog>
<xsl:for-each select=". | key('fields-by-lead', generate-id())[@name!=$lead-label]">
<xsl:element name="{@name}">
<xsl:value-of select="@value"/>
</xsl:element>
</xsl:for-each>
</dog>
</xsl:for-each>
</dogs>
</xsl:template>
</xsl:stylesheet>