Xslt转换/如何对实体进行分组
我想使用XSLT修改:Xslt转换/如何对实体进行分组,xslt,Xslt,我想使用XSLT修改: <Office Code="1" OtherAttribute="5"> <Customer CustomerId="0010" CodeModifier="A"/> <Customer CustomerId="0011" CodeModifier="B"/> <Customer CustomerId="0012" CodeModifier="B"/> </Office> <Office
<Office Code="1" OtherAttribute="5">
<Customer CustomerId="0010" CodeModifier="A"/>
<Customer CustomerId="0011" CodeModifier="B"/>
<Customer CustomerId="0012" CodeModifier="B"/>
</Office>
<Office Code="2" OtherAttribute="6">
<Customer CustomerId="2010" CodeModifier="A"/>
<Customer CustomerId="0011" CodeModifier="C"/>
</Office>
进入:
<Office Code="1A" OtherAttribute="5">
<Customer CustomerId="0010"/>
</Office>
<Office Code="1B" OtherAttribute="5">
<Customer CustomerId="0011"/>
<Customer CustomerId="0012"/>
</Office>
<Office Code="2A" OtherAttribute="6">
<Customer CustomerId="2010"/>
</Office>
<Office Code="2C" OtherAttribute="6">
<Customer CustomerId="0011"/>
</Office>
我的目标:
- 将具有相同CodeModifier的每个客户实体分组为Office实体。如果有多个CodeModifier,我将添加Office实体。将修改Office中的Code属性(将客户端的CodeModifier连接到Office中)
- (兼性但我认为很琐碎)抑制CodeModifier属性并保留所有其他属性
有人知道怎么做吗?此样式表应用于您的输入示例:
<!-- a key to group Customers by their office code + modifier -->
<xsl:key name="kCustomerGroup" match="Customer"
use="concat(../@Code, @CodeModifier)"
/>
<!-- identity template: copies everything that is not handled otherwise -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<!-- apply templates directly to customers. modify as necessary -->
<xsl:template match="/">
<xsl:apply-templates select="//Customer" mode="CustomerGroup" />
</xsl:template>
<xsl:template match="Customer" mode="CustomerGroup">
<xsl:variable name="officeCode" select="concat(../@Code, @CodeModifier)" />
<!-- if this Customer is first of his respective group... -->
<xsl:if test="
generate-id()
=
generate-id(key('kCustomerGroup', $officeCode)[1])
">
<!-- use for-each to switch the context node to the parent -->
<xsl:for-each select="..">
<xsl:copy>
<xsl:apply-templates select="@*" />
<!-- overwrite the @Code attribute -->
<xsl:attribute name="Code">
<xsl:value-of select="$officeCode" />
</xsl:attribute>
<!-- now handle the Customer group members -->
<xsl:apply-templates select="key('kCustomerGroup', $officeCode)" />
</xsl:copy>
</xsl:for-each>
</xsl:if>
</xsl:template>
<!-- remove unwanted attribute with empty template -->
<xsl:template match="Customer/@CodeModifier" />
及
此样式表应用于您的输入示例:
<!-- a key to group Customers by their office code + modifier -->
<xsl:key name="kCustomerGroup" match="Customer"
use="concat(../@Code, @CodeModifier)"
/>
<!-- identity template: copies everything that is not handled otherwise -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<!-- apply templates directly to customers. modify as necessary -->
<xsl:template match="/">
<xsl:apply-templates select="//Customer" mode="CustomerGroup" />
</xsl:template>
<xsl:template match="Customer" mode="CustomerGroup">
<xsl:variable name="officeCode" select="concat(../@Code, @CodeModifier)" />
<!-- if this Customer is first of his respective group... -->
<xsl:if test="
generate-id()
=
generate-id(key('kCustomerGroup', $officeCode)[1])
">
<!-- use for-each to switch the context node to the parent -->
<xsl:for-each select="..">
<xsl:copy>
<xsl:apply-templates select="@*" />
<!-- overwrite the @Code attribute -->
<xsl:attribute name="Code">
<xsl:value-of select="$officeCode" />
</xsl:attribute>
<!-- now handle the Customer group members -->
<xsl:apply-templates select="key('kCustomerGroup', $officeCode)" />
</xsl:copy>
</xsl:for-each>
</xsl:if>
</xsl:template>
<!-- remove unwanted attribute with empty template -->
<xsl:template match="Customer/@CodeModifier" />
及
这里有另一种方法,只使用匹配的模板
在MSXSL 4.0下测试为XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes"/>
<xsl:key name="kCustomerGroup" match="Customer"
use="concat(../@Code, @CodeModifier)"
/>
<xsl:template match="Office">
<xsl:apply-templates select="Customer[generate-id()
=
generate-id(key('kCustomerGroup',
concat(../@Code, @CodeModifier))[1])]"
/>
</xsl:template>
<xsl:template match="Customer">
<Office
Code="{concat(../@Code,@CodeModifier)}"
OtherAttribute="{../@OtherAttribute}">
<xsl:apply-templates select="key('kCustomerGroup',
concat(../@Code,@CodeModifier))" mode="copy"/>
</Office>
</xsl:template>
<xsl:template match="Customer" mode="copy">
<xsl:copy>
<xsl:copy-of select="@CustomerId"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出至:
<?xml version="1.0" encoding="UTF-8"?>
<Office Code="1A" OtherAttribute="5">
<Customer CustomerId="0010"/>
</Office>
<Office Code="1B" OtherAttribute="5">
<Customer CustomerId="0011"/>
<Customer CustomerId="0012"/>
</Office>
<Office Code="2A" OtherAttribute="6">
<Customer CustomerId="2010"/>
</Office>
<Office Code="2C" OtherAttribute="6">
<Customer CustomerId="0011"/>
</Office>
这里有另一种方法,只使用匹配的模板
在MSXSL 4.0下测试为XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes"/>
<xsl:key name="kCustomerGroup" match="Customer"
use="concat(../@Code, @CodeModifier)"
/>
<xsl:template match="Office">
<xsl:apply-templates select="Customer[generate-id()
=
generate-id(key('kCustomerGroup',
concat(../@Code, @CodeModifier))[1])]"
/>
</xsl:template>
<xsl:template match="Customer">
<Office
Code="{concat(../@Code,@CodeModifier)}"
OtherAttribute="{../@OtherAttribute}">
<xsl:apply-templates select="key('kCustomerGroup',
concat(../@Code,@CodeModifier))" mode="copy"/>
</Office>
</xsl:template>
<xsl:template match="Customer" mode="copy">
<xsl:copy>
<xsl:copy-of select="@CustomerId"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出至:
<?xml version="1.0" encoding="UTF-8"?>
<Office Code="1A" OtherAttribute="5">
<Customer CustomerId="0010"/>
</Office>
<Office Code="1B" OtherAttribute="5">
<Customer CustomerId="0011"/>
<Customer CustomerId="0012"/>
</Office>
<Office Code="2A" OtherAttribute="6">
<Customer CustomerId="2010"/>
</Office>
<Office Code="2C" OtherAttribute="6">
<Customer CustomerId="0011"/>
</Office>
完整而简短的XSLT 2.0解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*/*">
<xsl:for-each-group select="Customer" group-by="@CodeModifier">
<Office>
<xsl:copy-of select="../@*"/>
<xsl:attribute name="Code" select=
"concat(../@Code, current-grouping-key())"/>
<xsl:copy-of select="current-group()"/>
</Office>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
<Office Code="1A" OtherAttribute="5">
<Customer CustomerId="0010" CodeModifier="A"/>
</Office>
<Office Code="1B" OtherAttribute="5">
<Customer CustomerId="0011" CodeModifier="B"/>
<Customer CustomerId="0012" CodeModifier="B"/>
</Office>
<Office Code="2A" OtherAttribute="6">
<Customer CustomerId="2010" CodeModifier="A"/>
</Office>
<Office Code="2C" OtherAttribute="6">
<Customer CustomerId="0011" CodeModifier="C"/>
</Office>
应用于以下XML文档时(基于提供的XML片段,并将其包装到单个顶部元素中,使其成为格式良好的XML文档):
生成所需的正确结果:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*/*">
<xsl:for-each-group select="Customer" group-by="@CodeModifier">
<Office>
<xsl:copy-of select="../@*"/>
<xsl:attribute name="Code" select=
"concat(../@Code, current-grouping-key())"/>
<xsl:copy-of select="current-group()"/>
</Office>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
<Office Code="1A" OtherAttribute="5">
<Customer CustomerId="0010" CodeModifier="A"/>
</Office>
<Office Code="1B" OtherAttribute="5">
<Customer CustomerId="0011" CodeModifier="B"/>
<Customer CustomerId="0012" CodeModifier="B"/>
</Office>
<Office Code="2A" OtherAttribute="6">
<Customer CustomerId="2010" CodeModifier="A"/>
</Office>
<Office Code="2C" OtherAttribute="6">
<Customer CustomerId="0011" CodeModifier="C"/>
</Office>
完整而简短的XSLT 2.0解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*/*">
<xsl:for-each-group select="Customer" group-by="@CodeModifier">
<Office>
<xsl:copy-of select="../@*"/>
<xsl:attribute name="Code" select=
"concat(../@Code, current-grouping-key())"/>
<xsl:copy-of select="current-group()"/>
</Office>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
<Office Code="1A" OtherAttribute="5">
<Customer CustomerId="0010" CodeModifier="A"/>
</Office>
<Office Code="1B" OtherAttribute="5">
<Customer CustomerId="0011" CodeModifier="B"/>
<Customer CustomerId="0012" CodeModifier="B"/>
</Office>
<Office Code="2A" OtherAttribute="6">
<Customer CustomerId="2010" CodeModifier="A"/>
</Office>
<Office Code="2C" OtherAttribute="6">
<Customer CustomerId="0011" CodeModifier="C"/>
</Office>
应用于以下XML文档时(基于提供的XML片段,并将其包装到单个顶部元素中,使其成为格式良好的XML文档):
生成所需的正确结果:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*/*">
<xsl:for-each-group select="Customer" group-by="@CodeModifier">
<Office>
<xsl:copy-of select="../@*"/>
<xsl:attribute name="Code" select=
"concat(../@Code, current-grouping-key())"/>
<xsl:copy-of select="current-group()"/>
</Office>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
<Office Code="1A" OtherAttribute="5">
<Customer CustomerId="0010" CodeModifier="A"/>
</Office>
<Office Code="1B" OtherAttribute="5">
<Customer CustomerId="0011" CodeModifier="B"/>
<Customer CustomerId="0012" CodeModifier="B"/>
</Office>
<Office Code="2A" OtherAttribute="6">
<Customer CustomerId="2010" CodeModifier="A"/>
</Office>
<Office Code="2C" OtherAttribute="6">
<Customer CustomerId="0011" CodeModifier="C"/>
</Office>
您使用的条件与我一样。只有您的条件在谓词中,而我的条件在
;-)如果你仔细观察的话,我不会使用循环来做任何工作。你使用的条件和我一样。只有您的条件在谓词中,而我的条件在
;-)如果你仔细看的话,我不会用循环做任何工作。好问题,+1。请参阅我的答案,了解完整、非常简短且简单的XSLT 2.0解决方案。:)好问题,+1。请参阅我的答案,了解完整、非常简短且简单的XSLT 2.0解决方案。:)