我正在寻找一种方法:
以下是示例代码:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<books>
<mbean code="abc.def.ghi" name="com.booking.props:name=abcdefgh">
<attribute name="BName">abc123</attribute>
<depends optional-attribute-name="Bookname">mypersonnelbook</depends>
<attribute name="Type1">book.type1.name</attribute>
<attribute name="Properties">
bookname=book1
price=100
</attribute>
</mbean>
<mbean code="abc.def.ghi" name="com.booking.props:name=abcdefgh">
<attribute name="BName">abc123</attribute>
<depends optional-attribute-name="Bookname">mypersonnelbook</depends>
<attribute name="Type2">book.type2.name</attribute>
<attribute name="Properties">
bookname=book1
price=100
</attribute>
</mbean>
<us-country-factory>
<jndi-name>books/props/Classic</jndi-name>
<file-name>book1</file-name>
<state-location>central.wharehouse</state-location>
<store-property name="store" type="java.lang.String">abc</store-property>
<store-property name="storetype" type="java.lang.String">1223</store-property>
<store-property name="storelocation" type="java.lang.String">defsdgfd</store-property>
<store-property name="storecategory" type="java.lang.String">hjtbngb</store-property>
</us-country-factory>
<us-country-factory>
<jndi-name>books/props/Classic</jndi-name>
<file-name>book1</file-name>
<state-location>central.wharehouse</state-location>
<store-property name="store" type="java.lang.String">defghij</store-property>
<store-property name="storetype" type="java.lang.String">1223</store-property>
<store-property name="storelocation" type="java.lang.String">32das</store-property>
<store-property name="storecategory" type="java.lang.String">hjtbngb</store-property>
<store-property name="storeratings" type="java.lang.String">5</store-property>
我看的输出是:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<books>
<mbean code="abc.def.ghi" name="com.booking.props:name=abcdefgh">
<attribute name="BName">abc123</attribute>
<depends optional-attribute-name="Bookname">mypersonnelbook</depends>
<attribute name="Type1">book.type1.name</attribute>
<attribute name="Type2">book.type2.name</attribute>
<attribute name="Properties">
bookname=book1
price=100
</attribute>
</mbean>
<us-country-factory>
<jndi-name>books/props/Classic</jndi-name>
<file-name>book1</file-name>
<state-location>central.wharehouse</state-location>
<store-property name="store" type="java.lang.String">defghij</store-property>
<store-property name="storetype" type="java.lang.String">1223</store-property>
<store-property name="storelocation" type="java.lang.String">32das</store-property>
<store-property name="storecategory" type="java.lang.String">hjtbngb</store-property>
<store-property name="storeratings" type="java.lang.String">5</store-property>
</us-country-factory>
</books>
</us-country-factory>
</books>
这是我尝试过的xsl文件:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="mbeanName" match="//mbean/@name" use="."/>
<xsl:key name="mbeanCount" match="//mbean[generate-id(@name) = generate-id(key('mbeanName', @name)[1])]" use="count(.)"/>
<xsl:key name="us-country-factoryName" match="//us-country-factory[jndi-name/text()]" use="."/>
<xsl:key name="us-country-factoryCount" match="/us-country-factory[generate-id(jndi-name/text()) = generate-id(key('us-country-factoryName', jndi-name/text())[1])]" use="count(.)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="mbean[count(. | key('mbeanCount', /mbean/@name))]" />
<xsl:template match="mbean[count(. | key('us-country-factoryCount', us-country-factory[jndi-name/text()]))]" />
</xsl:stylesheet>
答案 0 :(得分:1)
由于您已将问题标记为XSLT 2.0,我建议尝试使用for-each-group
而不是密钥。这是一个示例样式表:
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="books">
<xsl:copy>
<xsl:for-each-group select="mbean" group-by="@name">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each-group select="current-group()/*" group-by="node-name(.)">
<xsl:for-each-group select="current-group()" group-by="@*">
<xsl:copy>
<xsl:copy-of select="@*, current-group()[last()]/node()"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
<xsl:for-each-group select="us-country-factory" group-by="jndi-name">
<xsl:copy>
<xsl:copy-of select="@*, *[not(@*)]"/>
<xsl:for-each-group select="current-group()/*[@*]" group-by="string-join(@*, '|')">
<xsl:copy>
<xsl:copy-of select="@*, current-group()[last()]/node()"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
改变
<books>
<mbean code="abc.def.ghi" name="com.booking.props:name=abcdefgh">
<attribute name="BName">abc123</attribute>
<depends optional-attribute-name="Bookname">mypersonnelbook</depends>
<attribute name="Type1">book.type1.name</attribute>
<attribute name="Properties">
bookname=book1
price=100
</attribute>
</mbean>
<mbean code="abc.def.ghi" name="com.booking.props:name=abcdefgh">
<attribute name="BName">abc123</attribute>
<depends optional-attribute-name="Bookname">mypersonnelbook</depends>
<attribute name="Type2">book.type2.name</attribute>
<attribute name="Properties">
bookname=book1
price=100
</attribute>
</mbean>
<us-country-factory>
<jndi-name>books/props/Classic</jndi-name>
<file-name>book1</file-name>
<state-location>central.wharehouse</state-location>
<store-property name="store" type="java.lang.String">abc</store-property>
<store-property name="storetype" type="java.lang.String">1223</store-property>
<store-property name="storelocation" type="java.lang.String">defsdgfd</store-property>
<store-property name="storecategory" type="java.lang.String">hjtbngb</store-property>
</us-country-factory>
<us-country-factory>
<jndi-name>books/props/Classic</jndi-name>
<file-name>book1</file-name>
<state-location>central.wharehouse</state-location>
<store-property name="store" type="java.lang.String">defghij</store-property>
<store-property name="storetype" type="java.lang.String">1223</store-property>
<store-property name="storelocation" type="java.lang.String">32das</store-property>
<store-property name="storecategory" type="java.lang.String">hjtbngb</store-property>
<store-property name="storeratings" type="java.lang.String">5</store-property>
</us-country-factory>
</books>
到
<books>
<mbean code="abc.def.ghi" name="com.booking.props:name=abcdefgh">
<attribute name="BName">abc123</attribute>
<attribute name="Type1">book.type1.name</attribute>
<attribute name="Properties">
bookname=book1
price=100
</attribute>
<attribute name="Type2">book.type2.name</attribute>
<depends optional-attribute-name="Bookname">mypersonnelbook</depends>
</mbean>
<us-country-factory>
<jndi-name>books/props/Classic</jndi-name>
<file-name>book1</file-name>
<state-location>central.wharehouse</state-location>
<store-property name="store" type="java.lang.String">defghij</store-property>
<store-property name="storetype" type="java.lang.String">1223</store-property>
<store-property name="storelocation" type="java.lang.String">32das</store-property>
<store-property name="storecategory" type="java.lang.String">hjtbngb</store-property>
<store-property name="storeratings" type="java.lang.String">5</store-property>
</us-country-factory>
</books>
我意识到这不是一个完整的解决方案,但它应该让您了解如何使用XSLT 2.0解决问题。您将精确定义“名称或值相似的合并节点”对于您的不同元素类型的含义,然后使用for-each-groups实现它。
以下是一些解释的尝试,代码
<xsl:for-each-group select="mbean" group-by="@name">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each-group select="current-group()/*" group-by="node-name(.)">
<xsl:for-each-group select="current-group()" group-by="@*">
<xsl:copy>
<xsl:copy-of select="@*, current-group()[last()]/node()"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
按mbean
属性对name
元素进行分组,然后对组中的第一个元素进行浅层复制(因为您要消除重复),然后复制任何属性。此外,内部for-each-group
按名称对mbean
组中的所有子元素进行分组(因此我们将所有attribute
元素分组,然后将所有depends
元素分组),然后按其属性进行分组值。这是一种简化,因为输入只有这些元素的一个属性。因此,在内部for-each-groups内,我们现在有一组例如attribute name="BName"
元素。我们对组中的第一个元素(组中的上下文节点)进行浅层复制,然后复制其属性,但复制组中最后一项的内容。