我的xslt背景很差,我需要转换看起来像这样的XML:
<row attribute1="1" attribute2="something" attribute3="somevalue">
<row attribute1="1" attribute2="something" attribute3="somevalue">
<row attribute1="2" attribute2="anotherthing" attribute3="somevalue">
看起来像这样:
<row attribute1="1">
<row attribute1="2">
转换任务还有两个要求。我想得到与上面相同的结果,但我想更改属性名称,例如:
<row new_name_for_attribute1="1">
<row new_name_for_attribute1="2">
最后一个要求是该方法可以应用于单个属性(如前面的示例),它们的一个子集(attribute1和attribute3),或行元素的所有属性
提前致谢。
答案 0 :(得分:2)
如果您希望了解有关XSLT错综复杂的更多信息,您可能有兴趣了解一种名为Muenchian Grouping的技术,可用于解决您的问题。要获得不同的行,请通过 attribute1 对其进行有效分组,然后为每个组选择组中的第一个元素。 (或丢弃不是第一个的元素)。 Muenchian Grouping是在XSLT 1.0中实现这一目标的最有效方法。
在这种情况下,您首先要定义一个键来表示您的组,在您的情况下是行元素,按 attribute1 分组
<xsl:key name="row" match="row" use="@attribute1" />
如果您之后想要选择不同的行元素,则应选择行元素,这些元素首先出现在其给定 attribute1
<xsl:apply-templates select="row[generate-id() = generate-id(key('row', @attribute1)[1])]" />
或者,您可以使用模板忽略重复的行元素(即不是组中的第一个)
<xsl:template match="row[generate-id() != generate-id(key('row', @attribute1)[1])]" />
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="row" match="row" use="@attribute1" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="row[generate-id() != generate-id(key('row', @attribute1)[1])]" />
</xsl:stylesheet>
应用于以下XML
<rows>
<row attribute1="1" attribute2="something" attribute3="somevalue" />
<row attribute1="1" attribute2="something" attribute3="somevalue" />
<row attribute1="2" attribute2="anotherthing" attribute3="somevalue" />
</rows>
以下是输出
<rows>
<row attribute1="1" attribute2="something" attribute3="somevalue"></row>
<row attribute1="2" attribute2="anotherthing" attribute3="somevalue"></row>
</rows>
可以轻松扩展XSLT以重命名属性或排除它们,如ljdelight的答案中所述。此外,如果您想在测试中包含第二个属性,可以像这样扩展您的密钥:
<xsl:key name="row" match="row" use="concat(@attribute1, '|', @attribute3)" />
要忽略重复项,模板会看起来像这个
<xsl:template match="row
[generate-id() != generate-id(key('row', concat(@attribute1, '|', @attribute3))[1])]" />
这里唯一需要注意的是使用管道字符|作为分隔符。如果需要,这可以是任何其他字符,只要它不在属性值中出现。
答案 1 :(得分:1)
您可以轻松转换XML。这里有一些代码,你可以学习和学习一些xsl。
<?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" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- drop a row that matches a previous row of the same id -->
<xsl:template match="row[ preceding-sibling::row/@attribute1 = @attribute1 ]" />
<!-- do stuff with the row. this template is equivalent to the default template copy. -->
<xsl:template match="row">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- drop attribute2 attributes -->
<xsl:template match="@attribute2" />
<!-- rename attribute1 -->
<xsl:template match="@attribute1">
<xsl:attribute name="new_name_for_attribute1">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
使用此输入:
<table>
<row attribute1="1" attribute2="something" attribute3="somevalue">
<p>foo</p>
</row>
<row attribute1="1" attribute2="something" attribute3="somevalue">
<p>bar</p>
</row>
<row attribute1="2" attribute2="anotherthing" attribute3="somevalue">
<p>bazinga</p>
</row>
</table>
获取此输出:
<table>
<row new_name_for_attribute1="1" attribute3="somevalue">
<p>foo</p>
</row>
<row new_name_for_attribute1="2" attribute3="somevalue">
<p>bazinga</p>
</row>
</table>