XSL muenchian-多层次分组和嵌套
XSL muenchian-grouping on multiple levels and nesting
输入:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<output>
<queries>
<query>
<parameters>
<parameter name="id">CTL-000002</parameter>
</parameters>
<queryResults>
<record id="1">
<column name="ConfigurationCapacity">9500.0000000</column>
<column name="configurationCode">CTL-3819</column>
<column name="compartmentCode">CTL-3819-01</column>
<column name="position">1</column>
<column name="CompartmentCapacity">2700</column>
<column name="unitName">G</column>
</record>
<record id="2">
<column name="ConfigurationCapacity">52120.0000000</column>
<column name="configurationCode">CTL-3819</column>
<column name="compartmentCode">CTL-3819-01</column>
<column name="position">1</column>
<column name="CompartmentCapacity">22950</column>
<column name="unitName">K</column>
</record>
<record id="3">
<column name="ConfigurationCapacity">9500.0000000</column>
<column name="configurationCode">CTL-3819</column>
<column name="compartmentCode">CTL-3819-02</column>
<column name="position">2</column>
<column name="CompartmentCapacity">1700</column>
<column name="unitName">G</column>
</record>
</queryResults>
</query>
</queries>
</output>
<trailer>
<id>CTL-000002</id>
<trailer_tag>0</trailer_tag>
</trailer>
<output>
<queries>
<query>
<parameters>
<parameter name="id">3</parameter>
</parameters>
<queryResults>
<record id="1">
<column name="ConfigurationCapacity">12</column>
<column name="configurationCode">LT</column>
<column name="compartmentCode">3819-01</column>
<column name="position">1</column>
<column name="CompartmentCapacity">70</column>
<column name="unitName">G</column>
</record>
<record id="2">
<column name="ConfigurationCapacity">500</column>
<column name="configurationCode">LT</column>
<column name="compartmentCode">3819-01</column>
<column name="position">1</column>
<column name="CompartmentCapacity">20</column>
<column name="unitName">K</column>
</record>
</queryResults>
</query>
</queries>
</output>
<trailer>
<id>3</id>
<trailer_tag>0</trailer_tag>
</trailer>
</root>
XSL:
<xsl:key name="queries" match="root/output/queries/query/queryResults/record" use="./column[@name='compartmentCode']"/>
<xsl:template match="@* | node()">
<xsl:variable name="uniqueCompartment" select="//record[string(column[@name='compartmentCode'])][count(. | key('queries', column[@name='compartmentCode'])[1]) = 1]"/>
<root>
<xsl:for-each select="//trailer">
<xsl:choose>
<xsl:when test="trailer_tag='0'">
<configurations>
<configuration>
<id>
<xsl:value-of select="//root/output/queries/query[parameters/parameter[@name='id'] = current()/id]/queryResults/record/column[@name='configurationCode']"/>
</id>
<compartments>
<!--I need to build the following structure for each unique compartmentCode-->
<xsl:for-each select="//root/output/queries/query/queryResults/record/column[@name='compartmentCode'][not(.=preceding::*)]">
<compartment>
<code>
<xsl:value-of select="."/>
</code>
<capacities>
<xsl:for-each select="$uniqueCompartment">
<capacity>
<!--I need for each unique Compartment to build the unit node for each unique UNIT that specific record has, and another node with the value of compartmentCapacity of that UNIT-->
<unit>
</unit>
<val>
</val>
</capacity>
</xsl:for-each>
</capacities>
</compartment>
</xsl:for-each>
</compartments>
</configuration>
</configurations>
<!--copy trailer node-->
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>
<!--something else-->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</root>
</xsl:template>
期望的输出:
<root>
<trailer>
<id>CTL-000002</id>
<trailer_tag>0</trailer_tag>
<configurations>
<configuration>
<id>CTL-3819</id>
<compartments>
<compartment>
<code>CTL-3819-01</code>
<capacities>
<capacity>
<unit>G</unit>
<val>2700</val>
</capacity>
<capacity>
<unit>KG</unit>
<val>22950</val>
</capacity>
</capacities>
</compartment>
<compartment>
<code>CTL-3819-02</code>
<capacities>
<capacity>
<unit>G</unit>
<val>1700</val>
</capacity>
</capacities>
</compartment>
</compartments>
</configuration>
</configurations>
</trailer>
<trailer>
<id>3</id>
<trailer_tag>0</trailer_tag>
<configurations>
<configuration>
<id>LT</id>
<compartments>
<compartment>
<code>3819-01</code>
<capacities>
<capacity>
<unit>G</unit>
<val>70</val>
</capacity>
<capacity>
<unit>K</unit>
<val>20</val>
</capacity>
</capacities>
</compartment>
</compartments>
</configuration>
</configurations>
</trailer>
</root>
我已经尝试阅读一些关于这种 muenchian 分组的文章,但似乎无法超过这一点。
我想要实现的是:
- 对于每个唯一 TRAILER/ID,在输出中复制整个节点
如果 trailer/ID 有一个具有相同 parameter/ID 的查询节点,则复制尾部节点并使用以下规则在其中构建配置节点:
- configuration/ID - 使用来自 'configurationCode' 的值填充此标记(每个查询都是唯一的)
- 对于查询中的每个唯一 'compartmentCode' 值,构建隔间节点
- 每个 compartmentCode 可以有一个或多个 'unitNames' 和 'compartmentCapacity' 值。我想为每个值构建单独的节点,如所需输出所示。
我离这个结果还有很长的路要走,但是如果有人能帮助我,请帮助我
谢谢。
你需要一个串联的键,因为你想要在 configurationCode
的上下文中有不同的 compartmentCode
值,所以你的键看起来像这样
<xsl:key name="queries"
match="record"
use="concat(column[@name='configurationCode'], '|', column[@name='compartmentCode'])"/>
然后,在 query
内获取唯一的 compartmentCode 值,执行此操作...
<xsl:for-each
select="queryResults/record[generate-id() = generate-id(key('queries', concat(column[@name='configurationCode'], '|', column[@name='compartmentCode']))[1])]">
试试这个(注意我是如何将一些代码分离到匹配的模板中的 query
以避免过多的代码嵌套,并使一些 xpath 更简单)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="queries" match="record" use="concat(column[@name='configurationCode'], '|', column[@name='compartmentCode'])"/>
<xsl:template match="/">
<root>
<xsl:for-each select="//trailer">
<xsl:choose>
<xsl:when test="trailer_tag='0'">
<xsl:copy>
<!--copy trailer node-->
<xsl:copy-of select="@*|node()"/>
<xsl:apply-templates select="//root/output/queries/query[parameters/parameter[@name='id'] = current()/id]" />
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<!--something else-->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template match="query">
<configurations>
<configuration>
<id>
<xsl:value-of select="queryResults/record/column[@name='configurationCode']"/>
</id>
<compartments>
<!--I need to build the following structure for each unique compartmentCode-->
<xsl:for-each select="queryResults/record[generate-id() = generate-id(key('queries', concat(column[@name='configurationCode'], '|', column[@name='compartmentCode']))[1])]">
<compartment>
<code>
<xsl:value-of select="column[@name='compartmentCode']"/>
</code>
<capacities>
<xsl:for-each select="key('queries', concat(column[@name='configurationCode'], '|', column[@name='compartmentCode']))">
<capacity>
<unit>
<xsl:value-of select="column[@name='unitName']"/>
</unit>
<val>
<xsl:value-of select="column[@name='CompartmentCapacity']"/>
</val>
</capacity>
</xsl:for-each>
</capacities>
</compartment>
</xsl:for-each>
</compartments>
</configuration>
</configurations>
</xsl:template>
</xsl:stylesheet>
输入:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<output>
<queries>
<query>
<parameters>
<parameter name="id">CTL-000002</parameter>
</parameters>
<queryResults>
<record id="1">
<column name="ConfigurationCapacity">9500.0000000</column>
<column name="configurationCode">CTL-3819</column>
<column name="compartmentCode">CTL-3819-01</column>
<column name="position">1</column>
<column name="CompartmentCapacity">2700</column>
<column name="unitName">G</column>
</record>
<record id="2">
<column name="ConfigurationCapacity">52120.0000000</column>
<column name="configurationCode">CTL-3819</column>
<column name="compartmentCode">CTL-3819-01</column>
<column name="position">1</column>
<column name="CompartmentCapacity">22950</column>
<column name="unitName">K</column>
</record>
<record id="3">
<column name="ConfigurationCapacity">9500.0000000</column>
<column name="configurationCode">CTL-3819</column>
<column name="compartmentCode">CTL-3819-02</column>
<column name="position">2</column>
<column name="CompartmentCapacity">1700</column>
<column name="unitName">G</column>
</record>
</queryResults>
</query>
</queries>
</output>
<trailer>
<id>CTL-000002</id>
<trailer_tag>0</trailer_tag>
</trailer>
<output>
<queries>
<query>
<parameters>
<parameter name="id">3</parameter>
</parameters>
<queryResults>
<record id="1">
<column name="ConfigurationCapacity">12</column>
<column name="configurationCode">LT</column>
<column name="compartmentCode">3819-01</column>
<column name="position">1</column>
<column name="CompartmentCapacity">70</column>
<column name="unitName">G</column>
</record>
<record id="2">
<column name="ConfigurationCapacity">500</column>
<column name="configurationCode">LT</column>
<column name="compartmentCode">3819-01</column>
<column name="position">1</column>
<column name="CompartmentCapacity">20</column>
<column name="unitName">K</column>
</record>
</queryResults>
</query>
</queries>
</output>
<trailer>
<id>3</id>
<trailer_tag>0</trailer_tag>
</trailer>
</root>
XSL:
<xsl:key name="queries" match="root/output/queries/query/queryResults/record" use="./column[@name='compartmentCode']"/>
<xsl:template match="@* | node()">
<xsl:variable name="uniqueCompartment" select="//record[string(column[@name='compartmentCode'])][count(. | key('queries', column[@name='compartmentCode'])[1]) = 1]"/>
<root>
<xsl:for-each select="//trailer">
<xsl:choose>
<xsl:when test="trailer_tag='0'">
<configurations>
<configuration>
<id>
<xsl:value-of select="//root/output/queries/query[parameters/parameter[@name='id'] = current()/id]/queryResults/record/column[@name='configurationCode']"/>
</id>
<compartments>
<!--I need to build the following structure for each unique compartmentCode-->
<xsl:for-each select="//root/output/queries/query/queryResults/record/column[@name='compartmentCode'][not(.=preceding::*)]">
<compartment>
<code>
<xsl:value-of select="."/>
</code>
<capacities>
<xsl:for-each select="$uniqueCompartment">
<capacity>
<!--I need for each unique Compartment to build the unit node for each unique UNIT that specific record has, and another node with the value of compartmentCapacity of that UNIT-->
<unit>
</unit>
<val>
</val>
</capacity>
</xsl:for-each>
</capacities>
</compartment>
</xsl:for-each>
</compartments>
</configuration>
</configurations>
<!--copy trailer node-->
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>
<!--something else-->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</root>
</xsl:template>
期望的输出:
<root>
<trailer>
<id>CTL-000002</id>
<trailer_tag>0</trailer_tag>
<configurations>
<configuration>
<id>CTL-3819</id>
<compartments>
<compartment>
<code>CTL-3819-01</code>
<capacities>
<capacity>
<unit>G</unit>
<val>2700</val>
</capacity>
<capacity>
<unit>KG</unit>
<val>22950</val>
</capacity>
</capacities>
</compartment>
<compartment>
<code>CTL-3819-02</code>
<capacities>
<capacity>
<unit>G</unit>
<val>1700</val>
</capacity>
</capacities>
</compartment>
</compartments>
</configuration>
</configurations>
</trailer>
<trailer>
<id>3</id>
<trailer_tag>0</trailer_tag>
<configurations>
<configuration>
<id>LT</id>
<compartments>
<compartment>
<code>3819-01</code>
<capacities>
<capacity>
<unit>G</unit>
<val>70</val>
</capacity>
<capacity>
<unit>K</unit>
<val>20</val>
</capacity>
</capacities>
</compartment>
</compartments>
</configuration>
</configurations>
</trailer>
</root>
我已经尝试阅读一些关于这种 muenchian 分组的文章,但似乎无法超过这一点。 我想要实现的是:
- 对于每个唯一 TRAILER/ID,在输出中复制整个节点
如果 trailer/ID 有一个具有相同 parameter/ID 的查询节点,则复制尾部节点并使用以下规则在其中构建配置节点:
- configuration/ID - 使用来自 'configurationCode' 的值填充此标记(每个查询都是唯一的)
- 对于查询中的每个唯一 'compartmentCode' 值,构建隔间节点
- 每个 compartmentCode 可以有一个或多个 'unitNames' 和 'compartmentCapacity' 值。我想为每个值构建单独的节点,如所需输出所示。
我离这个结果还有很长的路要走,但是如果有人能帮助我,请帮助我
谢谢。
你需要一个串联的键,因为你想要在 configurationCode
的上下文中有不同的 compartmentCode
值,所以你的键看起来像这样
<xsl:key name="queries"
match="record"
use="concat(column[@name='configurationCode'], '|', column[@name='compartmentCode'])"/>
然后,在 query
内获取唯一的 compartmentCode 值,执行此操作...
<xsl:for-each
select="queryResults/record[generate-id() = generate-id(key('queries', concat(column[@name='configurationCode'], '|', column[@name='compartmentCode']))[1])]">
试试这个(注意我是如何将一些代码分离到匹配的模板中的 query
以避免过多的代码嵌套,并使一些 xpath 更简单)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="queries" match="record" use="concat(column[@name='configurationCode'], '|', column[@name='compartmentCode'])"/>
<xsl:template match="/">
<root>
<xsl:for-each select="//trailer">
<xsl:choose>
<xsl:when test="trailer_tag='0'">
<xsl:copy>
<!--copy trailer node-->
<xsl:copy-of select="@*|node()"/>
<xsl:apply-templates select="//root/output/queries/query[parameters/parameter[@name='id'] = current()/id]" />
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<!--something else-->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template match="query">
<configurations>
<configuration>
<id>
<xsl:value-of select="queryResults/record/column[@name='configurationCode']"/>
</id>
<compartments>
<!--I need to build the following structure for each unique compartmentCode-->
<xsl:for-each select="queryResults/record[generate-id() = generate-id(key('queries', concat(column[@name='configurationCode'], '|', column[@name='compartmentCode']))[1])]">
<compartment>
<code>
<xsl:value-of select="column[@name='compartmentCode']"/>
</code>
<capacities>
<xsl:for-each select="key('queries', concat(column[@name='configurationCode'], '|', column[@name='compartmentCode']))">
<capacity>
<unit>
<xsl:value-of select="column[@name='unitName']"/>
</unit>
<val>
<xsl:value-of select="column[@name='CompartmentCapacity']"/>
</val>
</capacity>
</xsl:for-each>
</capacities>
</compartment>
</xsl:for-each>
</compartments>
</configuration>
</configurations>
</xsl:template>
</xsl:stylesheet>