Xml 选择唯一属性组
我的xslt背景很差,需要转换如下所示的XML:Xml 选择唯一属性组,xml,xslt,Xml,Xslt,我的xslt背景很差,需要转换如下所示的XML: <row attribute1="1" attribute2="something" attribute3="somevalue"> <row attribute1="1" attribute2="something" attribute3="somevalue"> <row attribute1="2" attribute2="anotherthing" attribute3="somevalue"> &l
<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 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)或行元素的所有属性
提前感谢。您可以轻松地转换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>
福
巴辛加
您可以轻松地转换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>
福
巴辛加
如果您想进一步了解XSLT的复杂性,您可能有兴趣了解一种称为XSLT的技术,它可以用来解决您的问题。要获得不同的行,可以通过attribute1对它们进行有效分组,然后为每个组选择组中的第一个元素。(或丢弃不是第一个的元素)。在XSLT1.0中,Muenchian分组是实现这一点的最有效方法
在本例中,首先定义一个键来指示您的组,在本例中,该组是按属性1分组的行元素
<xsl:key name="row" match="row" use="@attribute1" />
<xsl:apply-templates select="row[generate-id() = generate-id(key('row', @attribute1)[1])]" />
然后,如果您想选择不同的行元素,您可以为其给定的属性1选择键中首先出现的行元素
<xsl:key name="row" match="row" use="@attribute1" />
<xsl:apply-templates select="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])]" />
这里唯一需要注意的是使用管道字符|作为分隔符。如果需要,这可以是任何其他字符,只要它不出现在属性值中 如果您想进一步了解XSLT的复杂性,您可能有兴趣了解一种称为XSLT的技术,它可以用来解决您的问题。要获得不同的行,可以通过attribute1对它们进行有效分组,然后为每个组选择组中的第一个元素。(或丢弃不是第一个的元素)。在XSLT1.0中,Muenchian分组是实现这一点的最有效方法 在本例中,首先定义一个键来指示您的组,在本例中,该组是按属性1分组的行元素
<xsl:key name="row" match="row" use="@attribute1" />
<xsl:apply-templates select="row[generate-id() = generate-id(key('row', @attribute1)[1])]" />
然后,如果您想选择不同的行元素,您可以为其给定的属性1选择键中首先出现的行元素
<xsl:key name="row" match="row" use="@attribute1" />
<xsl:apply-templates select="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])]" />
这里唯一需要注意的是使用管道字符|作为分隔符。如果需要,这可以是任何其他字符,只要它不出现在属性值中 非常感谢,它成功了。如果我想通过多个属性进行过滤,我应该将它们添加到“前面的兄弟姐妹”表达式中?对。如果您想按不同的attribute1和attribute3对进行筛选,那么应该是行[前面的兄弟姐妹::行/\@attribute1=\@attribute1和前面的兄弟姐妹::行/\@attribute3=\@attribute3](忽略反斜杠…因此抱怨我试图通知太多用户)是否有可能更改和标记文本?我会试着回答,但如果我误解了你,你必须开始一个新的问题。。。你只需要在“表”上匹配;不使用xsl:copy,只输出“Table”元素。。。非常感谢,它成功了。如果我想通过多个属性进行过滤,我应该将它们添加到“前面的兄弟姐妹”表达式中?对。如果您想按不同的attribute1和attribute3对进行筛选,那么应该是行[前面的同级::行/\@attribute1=\@attribute1和前面的同级::行/\@attribute3=\@attribute3](忽略反斜杠…所以