完整的 xslt 新手。如何在 xslt 版本 1.0 中合并这 2 个 xml 源?应用分组和排序?

发布于 2024-10-14 06:23:19 字数 12515 浏览 4 评论 0原文

转换源

Data1.xml

 <DEALERSHIP reg_number="01234567">
 <MANUFACTURER name="VAUXHALL">
     <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20040331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
     <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>2.5</CAR_ENG>
        <CAR_MODEL>CALIBRA</CAR_MODEL>
        <CAR_REG_DATE>20030331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>
</MANUFACTURER>
<MANUFACTURER name="FORD">
     <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>2.5</CAR_ENG>
        <CAR_MODEL>CMAX</CAR_MODEL>
        <CAR_REG_DATE>20050331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
    </MANUFACTURER>

外部数据 Data2.xml

<DEALERSHIP reg_number="01234567">
<MANUFACTURER name="VAUXHALL">
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>
</MANUFACTURER>
<MANUFACTURER name="TOYOTA">
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>Corolla</CAR_MODEL>
        <CAR_REG_DATE>20030812</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
</MANUFACTURER>

需要输出

<DEALERSHIP reg_number="01234567">
<MANUFACTURER name="VAUXHALL">
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20040331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>2.5</CAR_ENG>
        <CAR_MODEL>CALIBRA</CAR_MODEL>
        <CAR_REG_DATE>20030331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>

</MANUFACTURER>
<MANUFACTURER name="FORD">
    <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>2.5</CAR_ENG>
        <CAR_MODEL>CMAX</CAR_MODEL>
        <CAR_REG_DATE>20050331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
</MANUFACTURER>
<MANUFACTURER name="TOYOTA">
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>Corolla</CAR_MODEL>
        <CAR_REG_DATE>20030812</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
</MANUFACTURER>

我的第一次尝试 xsl

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" xmlns:externalSupplier="externalSupplier://uk.co.skyline.XslConnector"
xmlns:consol="consol://uk.co.skyline.Xslconsolidated"
exclude-result-prefixes="externalSupplier consol">

<xsl:output method="xml" />



<!-- *** Parameters *** -->
<!-- ****************** -->
<xsl:param name="dealerNo"></xsl:param>  <!-- ** dealer Reg No being processed -->
<xsl:param name="supplier"></xsl:param> 
<xsl:param name="cust"></xsl:param>          


<!-- Load xml from external into variables -->
<!-- ************************************* -->
<!--
    <xsl:variable name="externalStuff" select="externalSupplier:getData(
    $dealerNo,  $supplier, $cust)"></xsl:variable>
-->

<xsl:variable name="externalStuff" 
select="document('Data2.xml')/*"></xsl:variable>



<xsl:template match="/">


    <xsl:for-each select="DEALERSHIP">

        <xsl:variable name="RegNum" select="@reg_number" />

        <xsl:element name="{name()}">
            <xsl:apply-templates select="." mode="copyAttributes" />

            <xsl:for-each select="MANUFACTURER">
                <xsl:variable name="manName" select="@name" />
                <xsl:apply-templates select=".">

                    <xsl:with-param name="externalMan"
                        select="$externalStuff[@reg_number = 
                        $RegNum]/MANUFACTURER[@name = $manName]" />
                </xsl:apply-templates>
            </xsl:for-each>
        </xsl:element>

    </xsl:for-each>

</xsl:template>

<!-- Process the MANUFACTURER elements -->
<!-- **************************** -->
<xsl:template match="MANUFACTURER">
    <xsl:param name="externalMan" />

    <!-- Get the reg number of the dealer -->
    <xsl:variable name="regNum" select="../@reg_number" />

    <!-- Get the manufacturer name -->
    <xsl:variable name="eManName" select="@name" />

    <xsl:element name="{name()}">
        <xsl:apply-templates select="." mode="copyAttributes" />

        <xsl:variable name="cars" select="CAR" />


        <xsl:apply-templates
            select="CAR | $externalMan/CAR[not (CAR_REG_DATE = 
            $cars/CAR_REG_DATE and CAR_MODEL = $cars/CAR_MODEL ) ]">

            <xsl:sort select="CAR_REG_DATE" data-type="number" 
            order="descending" />
            <xsl:sort select="CAR_MODEL" data-type="number" 
            order="descending" />
        </xsl:apply-templates>

    </xsl:element>

</xsl:template>


<!-- Process the CAR elements -->
<!-- **************************** -->
<xsl:template match="CAR">
    <xsl:param name="externalMan" />

    <xsl:choose>


        <xsl:when test="CAR_VIN">
            <xsl:copy-of select="." />
        </xsl:when>
        <xsl:otherwise>


            <xsl:if
                test="string-length(CAR_REG_DATE) = 8">

                <CAR>
                    <xsl:copy-of select="*" />
                    <CAR_VIN>
                        <xsl:value-of
                            select="consol:getConSol(../../@reg_number, 
                            CAR_REG_DATE, CAR_MODEL)" />
                    </CAR_VIN>
                </CAR>

            </xsl:if>

        </xsl:otherwise>
    </xsl:choose>
</xsl:template>




<!-- Copy the element's attributes to the output -->
<!-- ******************************************* -->
<xsl:template match="DEALERSHIP | MANUFACTURER" mode="copyAttributes">

    <xsl:for-each select="attribute::*">
        <xsl:attribute name="{name()}"><xsl:value-of select="." />
        </xsl:attribute>
    </xsl:for-each>
</xsl:template>

这种转换发生在服务器端,通过 java 启动。

正如您从样式表中看到的,我必须通过调用某些 java 处理来包含 Data2.xml。我已使用 document() 进行调试。

我设法使来自/到 java 输入的调用正常工作,并且 xslt 输出的主要结构正常工作。如果任何数据中不存在 CAR_VIN,则对 java 的调用会在每个 CAR 元素的转换时发生。给定的数据包括所有 CAR_VIN,以避免调用此 java.util.Car_VIN。

它是专门与合并相关的 xsl 逻辑和代码,我是新手,需要一些帮助。

合并逻辑是将数据源 MANUFACTURERS 和子元素组合起来。其中两个源具有相同的 CAR 元素,其子元素为 CAR_REG_DATE 和 CAR_MODEL 内容相同,然后仅包含 Data1.xml 或 Data2.xml 中计数最高的数据 那个独特的组合。如果组合在两个数据源中具有相同的数据量,则使用转换源 xml,在上述情况下为 Data1.xml。 生成的元素需要按每个单独的 MANUFATURER 元素中的 CAR_REG_DATE 降序排序。 因此,在上面的数据示例中,您可以看到必要的输出包括所有 MANUFACTURERS ;沃克斯豪尔、福特、丰田。 对于 Vauxhall Astra 20060331,输出包含 Data2.xml ASTRA 20060331 中的数据,不包括 Data1.xml 中的相同数据组合 Vauxhall Astra 的所有其他案例(非 20060331)均包含在 Data1.xml 的输出中,每个制造商中的所有汽车均按 CAR_REG_DATE 降序排序 福特制造商数据包含在 Data1 按 CAR_REG_DATE desc 排序的输出中。 丰田制造商数据包含在 Data2 有序 CAR_REG_DATE desc 的输出中。

我最初提出使用联合运算符进行合并的想法,其中 Data2.xml CAR_REG_DATE 和 CAR_MODEL 内容值与 Data1.xml CAR_REG_DATE 不同,但这会在没有匹配数据 CAR_REG_DATE 和 CAR_MODEL 时从 Data2.xml 中排除任何数据Data1.xml 中的组合。另外(当我想到这一点时),当 DATA1.xml 中存在相同的 CAR_REG_DATE 和 CAR_MODEL 组合时,无论任一数据源中的计数如何,它都会从 Data2.xsml 中排除数据,这绝对不是我想要的。

应用 stylesheet.xsl 的结果

<?xml version="1.0" encoding="UTF-8"?>

12345678901234567 1.9 阿斯特拉 20060331 一个 HH54 RRY 红色的 12345678901234567 1.9 阿斯特拉 20040331 一个 HH54 RRY 红色的 12345678901234567 2.5 卡里布拉 20030331 一个 HH54 RRY 蓝色的 12345678901234567 2.5 克马克斯 20050331 一个 HH54 RRY 红色的

然后我想到了将源文档和外部文档合并到一个局部变量中并将这个合并的 MANUFACTURER 传递到模板中并循环的想法 每个汽车元素。我可以通过以 XXX 开头的 CAR_VIN 的内容来区分 Data1.xml 和 Data2.xml CAR 元素。所以我想我会循环遍历每个 合并 CAR 元素并选择源文档和外部文档的计数,并根据结果包含外部或排除源。

这是否可能,我将如何执行此操作,或者是否有正确的方法执行此操作,请记住我是 xslt 处理的完全新手?

任何有关此问题的帮助将不胜感激。

您好,感谢您的回复

我已经编辑了数据集以避免 rsi。

简而言之,我需要实现以下逻辑 -

无论来源 Data1.xml 或 Data2.xml 具有更多数量的 CAR_REG_DATE 和 CAR_MODEL (在 CAR 内)的唯一组合 在输出中包含该源数据 - 排除具有相同组合的其他源数据。

所有 CAR_REG_DATE - CAR_MODEL 唯一组合都需要包含在两个来源中。一旦合并,每个制造商中的 CAR_REG_DATE 降序排列

因此采用 Astra-20060331 的 Vauxhall MANUFACTURER

独特组合 - Data1.xml 有 1,Data2.xml 有 2。

我需要从为此组合设置的 Data2.xml 输出 Astras 20060331 并忽略Data1.xml Astras 20060331 1 次出现,如上面的 requiredoutput.xml 所示

Dimi 我非常感谢您的评论。我想这是我的问题;我试图审视这个问题并将其分解成更小的部分,但在这里失败了。发现 xsl:variable 是不可变的,我仍然感到震惊。 (或者看起来是这样)。

The Transformation source

Data1.xml

 <DEALERSHIP reg_number="01234567">
 <MANUFACTURER name="VAUXHALL">
     <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20040331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
     <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>2.5</CAR_ENG>
        <CAR_MODEL>CALIBRA</CAR_MODEL>
        <CAR_REG_DATE>20030331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>
</MANUFACTURER>
<MANUFACTURER name="FORD">
     <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>2.5</CAR_ENG>
        <CAR_MODEL>CMAX</CAR_MODEL>
        <CAR_REG_DATE>20050331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
    </MANUFACTURER>

The external data
Data2.xml

<DEALERSHIP reg_number="01234567">
<MANUFACTURER name="VAUXHALL">
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>
</MANUFACTURER>
<MANUFACTURER name="TOYOTA">
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>Corolla</CAR_MODEL>
        <CAR_REG_DATE>20030812</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
</MANUFACTURER>

required output

<DEALERSHIP reg_number="01234567">
<MANUFACTURER name="VAUXHALL">
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20060331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>ASTRA</CAR_MODEL>
        <CAR_REG_DATE>20040331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
    <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>2.5</CAR_ENG>
        <CAR_MODEL>CALIBRA</CAR_MODEL>
        <CAR_REG_DATE>20030331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>BLUE</COLOUR>
    </CAR>

</MANUFACTURER>
<MANUFACTURER name="FORD">
    <CAR>
        <CAR_VIN>12345678901234567</CAR_VIN>
        <CAR_ENG>2.5</CAR_ENG>
        <CAR_MODEL>CMAX</CAR_MODEL>
        <CAR_REG_DATE>20050331</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>HH54 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
</MANUFACTURER>
<MANUFACTURER name="TOYOTA">
    <CAR>
        <CAR_VIN>XXX12345678901234567</CAR_VIN>
        <CAR_ENG>1.9</CAR_ENG>
        <CAR_MODEL>Corolla</CAR_MODEL>
        <CAR_REG_DATE>20030812</CAR_REG_DATE>
        <TRANSMISSION>A</TRANSMISSION>
        <CAR_REG>SS00 RRY</CAR_REG>
        <COLOUR>RED</COLOUR>
    </CAR>
</MANUFACTURER>

My first attempt xsl

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" xmlns:externalSupplier="externalSupplier://uk.co.skyline.XslConnector"
xmlns:consol="consol://uk.co.skyline.Xslconsolidated"
exclude-result-prefixes="externalSupplier consol">

<xsl:output method="xml" />



<!-- *** Parameters *** -->
<!-- ****************** -->
<xsl:param name="dealerNo"></xsl:param>  <!-- ** dealer Reg No being processed -->
<xsl:param name="supplier"></xsl:param> 
<xsl:param name="cust"></xsl:param>          


<!-- Load xml from external into variables -->
<!-- ************************************* -->
<!--
    <xsl:variable name="externalStuff" select="externalSupplier:getData(
    $dealerNo,  $supplier, $cust)"></xsl:variable>
-->

<xsl:variable name="externalStuff" 
select="document('Data2.xml')/*"></xsl:variable>



<xsl:template match="/">


    <xsl:for-each select="DEALERSHIP">

        <xsl:variable name="RegNum" select="@reg_number" />

        <xsl:element name="{name()}">
            <xsl:apply-templates select="." mode="copyAttributes" />

            <xsl:for-each select="MANUFACTURER">
                <xsl:variable name="manName" select="@name" />
                <xsl:apply-templates select=".">

                    <xsl:with-param name="externalMan"
                        select="$externalStuff[@reg_number = 
                        $RegNum]/MANUFACTURER[@name = $manName]" />
                </xsl:apply-templates>
            </xsl:for-each>
        </xsl:element>

    </xsl:for-each>

</xsl:template>

<!-- Process the MANUFACTURER elements -->
<!-- **************************** -->
<xsl:template match="MANUFACTURER">
    <xsl:param name="externalMan" />

    <!-- Get the reg number of the dealer -->
    <xsl:variable name="regNum" select="../@reg_number" />

    <!-- Get the manufacturer name -->
    <xsl:variable name="eManName" select="@name" />

    <xsl:element name="{name()}">
        <xsl:apply-templates select="." mode="copyAttributes" />

        <xsl:variable name="cars" select="CAR" />


        <xsl:apply-templates
            select="CAR | $externalMan/CAR[not (CAR_REG_DATE = 
            $cars/CAR_REG_DATE and CAR_MODEL = $cars/CAR_MODEL ) ]">

            <xsl:sort select="CAR_REG_DATE" data-type="number" 
            order="descending" />
            <xsl:sort select="CAR_MODEL" data-type="number" 
            order="descending" />
        </xsl:apply-templates>

    </xsl:element>

</xsl:template>


<!-- Process the CAR elements -->
<!-- **************************** -->
<xsl:template match="CAR">
    <xsl:param name="externalMan" />

    <xsl:choose>


        <xsl:when test="CAR_VIN">
            <xsl:copy-of select="." />
        </xsl:when>
        <xsl:otherwise>


            <xsl:if
                test="string-length(CAR_REG_DATE) = 8">

                <CAR>
                    <xsl:copy-of select="*" />
                    <CAR_VIN>
                        <xsl:value-of
                            select="consol:getConSol(../../@reg_number, 
                            CAR_REG_DATE, CAR_MODEL)" />
                    </CAR_VIN>
                </CAR>

            </xsl:if>

        </xsl:otherwise>
    </xsl:choose>
</xsl:template>




<!-- Copy the element's attributes to the output -->
<!-- ******************************************* -->
<xsl:template match="DEALERSHIP | MANUFACTURER" mode="copyAttributes">

    <xsl:for-each select="attribute::*">
        <xsl:attribute name="{name()}"><xsl:value-of select="." />
        </xsl:attribute>
    </xsl:for-each>
</xsl:template>

This transformation happens server side initiated through java.

As you can see from the stylesheet I have to include the Data2.xml through a call to some java processing. I have used the document() for debug purposes.

I managed to get the calls from/to the java inputs working and the main structure of the xslt output working. Where a CAR_VIN is not present in any data the call to java happens on transform of every CAR element. The given data includes all CAR_VIN's to avoid call outs to this java.

Its the xsl logic and code specifically relating to the merging that I'm new to and need some help on.

The merge logic is to combine both data sources MANUFACTURERS and child elements. Where both sources have identical CAR elements whose child elements,
CAR_REG_DATE and CAR_MODEL content is the same then only include the data from either Data1.xml or Data2.xml whichever has the highest count of
that unique combination. If a combinaton has the same amount of data in both data sources then use the transformation source xml, in the above case Data1.xml.
The resulting elements need to be ordered by CAR_REG_DATE descending in each individual MANUFATURER element.
So in the above data example you can see that the necesary output includes all MANUFACTURERS ; VAUXHALL, FORD, TOYOTA.
In the case of Vauxhall Astra 20060331 the output contains the data from Data2.xml ASTRA 20060331 excluding the same data combination from Data1.xml
All other cases of Vauxhall Astra (non 20060331) are included in the ouput from Data1.xml all the CARS in each MANUFACTURER being ordered by CAR_REG_DATE descending
Ford Manaufacturer data is included in the output from Data1 ordered CAR_REG_DATE desc.
Toyota Manaufacturer data is included in the output from Data2 ordered CAR_REG_DATE desc.

I initially came up with the idea of merging using the union operator where Data2.xml CAR_REG_DATE and CAR_MODEL content value is not the same as Data1.xml CAR_REG_DATE but this would exclude any data from Data2.xml when there was no matching data CAR_REG_DATE and CAR_MODEL combination in Data1.xml. Also (when I thought about it) it will allways exclude data from Data2.xsml when the same combination CAR_REG_DATE and CAR_MODEL was in DATA1.xml irrespective of counts in either data source, which is definately not what I want.

Result from applying stylesheet.xsl

<?xml version="1.0" encoding="UTF-8"?>

12345678901234567
1.9
ASTRA
20060331
A
HH54 RRY
RED

12345678901234567
1.9
ASTRA
20040331
A
HH54 RRY
RED

12345678901234567
2.5
CALIBRA
20030331
A
HH54 RRY
BLUE

12345678901234567
2.5
CMAX
20050331
A
HH54 RRY
RED

hen I came up with the idea of merging both the source document and external document together into a local variable and passing this merged MANUFACTURER into a template and looping through
every CAR element. I can differentiate between Data1.xml and Data2.xml CAR elements by the content of CAR_VIN starting with XXX.So I thought I would loop through every
merged CAR element and select counts for source document and external document and include external or exclude source based on the result.

Is this possible and how would I go about doing this or is there a correct way of doing this keeping in mind I am a complete newbie to xslt processing ?

Any help with this problem would be really appreciated.

Hi thanks for the response

I've edited the data set to avoid rsi.

In a nutshell I need to implement the following logic -

Whichever source Data1.xml or Data2.xml has the greater number of unique combination of CAR_REG_DATE and CAR_MODEL (within CAR)
include that sources data in the output - exclude the other sources data with the same combination.

All CAR_REG_DATE - CAR_MODEL unique combinations need to be included from both sources. Ordered CAR_REG_DATE descending in each MANUFACTURER, once merged

So taking the Vauxhall MANUFACTURER

unique combination of Astra- 20060331 - Data1.xml has 1 and Data2.xml has 2.

I need to output the Astras 20060331 from Data2.xml set for this combination and disregard Data1.xml Astras 20060331 1 occurence as shown in the requiredoutput.xml above

Dimi I do appreciate your comment . I think this is my problem; I'm trying to look at the problem and break it down into smaller pieces but am failing here. I'm still in shock from discovering that the xsl:variable is immutable. (or so it seems).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

请叫√我孤独 2024-10-21 06:23:19

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kCarByMan-Mod-Date"
             match="CAR"
             use="concat(../@name,'+',CAR_MODEL,'+',CAR_REG_DATE)"/>
    <xsl:variable name="vSource2" select="document('Data2.xml')"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="node()|@*" mode="copy">
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="DEALERSHIP">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                <xsl:with-param name="pSource2" select="$vSource2"/>
            </xsl:apply-templates>
            <xsl:apply-templates
                 select="$vSource2/*/MANUFACTURER[
                                        not(@name = current()/*/@name)
                                     ]">
                <xsl:with-param name="pSource2" select="/"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="MANUFACTURER">
        <xsl:param name="pSource2"/>
        <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                <xsl:with-param name="pSource2" select="$pSource2"/>
            </xsl:apply-templates>
            <xsl:apply-templates
                 select="$pSource2/*/MANUFACTURER[
                                        @name = current()/@name
                                     ]/node()">
                <xsl:with-param name="pSource2" select="/"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="CAR"/>
    <xsl:template
         match="CAR[count(.|key('kCarByMan-Mod-Date',
                                concat(../@name,'+',CAR_MODEL,'+',CAR_REG_DATE)
                            )[1]
                    ) = 1]">
        <xsl:param name="pSource2"/>
        <xsl:variable
             name="vKey"
             select="concat(../@name,'+',CAR_MODEL,'+',CAR_REG_DATE)"/>
        <xsl:variable name="vGroup" select="key('kCarByMan-Mod-Date',$vKey)"/>
        <xsl:for-each select="$pSource2">
            <xsl:variable name="vGroup2"
                          select="key('kCarByMan-Mod-Date',$vKey)"/>
            <xsl:apply-templates
                 select="$vGroup[not(count($vGroup2) > count($vGroup))]"
                 mode="copy"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

输出:

<DEALERSHIP reg_number="01234567">
    <MANUFACTURER name="VAUXHALL">
        <CAR>
            <CAR_VIN>12345678901234567</CAR_VIN>
            <CAR_ENG>1.9</CAR_ENG>
            <CAR_MODEL>ASTRA</CAR_MODEL>
            <CAR_REG_DATE>20040331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>HH54 RRY</CAR_REG>
            <COLOUR>RED</COLOUR>
        </CAR>
        <CAR>
            <CAR_VIN>12345678901234567</CAR_VIN>
            <CAR_ENG>2.5</CAR_ENG>
            <CAR_MODEL>CALIBRA</CAR_MODEL>
            <CAR_REG_DATE>20030331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>HH54 RRY</CAR_REG>
            <COLOUR>BLUE</COLOUR>
        </CAR>
        <CAR>
            <CAR_VIN>XXX12345678901234567</CAR_VIN>
            <CAR_ENG>1.9</CAR_ENG>
            <CAR_MODEL>ASTRA</CAR_MODEL>
            <CAR_REG_DATE>20060331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>SS00 RRY</CAR_REG>
            <COLOUR>BLUE</COLOUR>
        </CAR>
        <CAR>
            <CAR_VIN>XXX12345678901234567</CAR_VIN>
            <CAR_ENG>1.9</CAR_ENG>
            <CAR_MODEL>ASTRA</CAR_MODEL>
            <CAR_REG_DATE>20060331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>SS00 RRY</CAR_REG>
            <COLOUR>BLUE</COLOUR>
        </CAR>
    </MANUFACTURER>
    <MANUFACTURER name="FORD">
        <CAR>
            <CAR_VIN>12345678901234567</CAR_VIN>
            <CAR_ENG>2.5</CAR_ENG>
            <CAR_MODEL>CMAX</CAR_MODEL>
            <CAR_REG_DATE>20050331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>HH54 RRY</CAR_REG>
            <COLOUR>RED</COLOUR>
        </CAR>
    </MANUFACTURER>
    <MANUFACTURER name="TOYOTA">
        <CAR>
            <CAR_VIN>XXX12345678901234567</CAR_VIN>
            <CAR_ENG>1.9</CAR_ENG>
            <CAR_MODEL>Corolla</CAR_MODEL>
            <CAR_REG_DATE>20030812</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>SS00 RRY</CAR_REG>
            <COLOUR>RED</COLOUR>
        </CAR>
    </MANUFACTURER>
</DEALERSHIP>

注意:按制造商、型号和日期分组。遍历Data1.xmlDEALERSHIP 规则(仅匹配来自 Data1.xml 的节点):复制自身,将模板应用到以 Data2.xml 作为第二源的子级,应用模板来自 Data2.xml 的制造商不存在于 Data1.xml 中。 MANUFACTURER 规则(匹配来自 Data1.xmlData2.xml 的节点):复制自身,将模板应用到具有 pSource2< 的子级/code> 参数作为第二个源,将模板应用于属于第二个源中同一制造商的 CAR(对于 Data2.xml 中不存在的制造商,这将为空>Data1.xml)。空 CAR 默认规则。 “同类首创”CAR 规则:如果同一组中没有来自第二个源的更多项目,则复制当前组(这意味着对于相同数量,两者都会被复制。澄清以下情况下的行为这是不希望的。

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kCarByMan-Mod-Date"
             match="CAR"
             use="concat(../@name,'+',CAR_MODEL,'+',CAR_REG_DATE)"/>
    <xsl:variable name="vSource2" select="document('Data2.xml')"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="node()|@*" mode="copy">
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="DEALERSHIP">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                <xsl:with-param name="pSource2" select="$vSource2"/>
            </xsl:apply-templates>
            <xsl:apply-templates
                 select="$vSource2/*/MANUFACTURER[
                                        not(@name = current()/*/@name)
                                     ]">
                <xsl:with-param name="pSource2" select="/"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="MANUFACTURER">
        <xsl:param name="pSource2"/>
        <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                <xsl:with-param name="pSource2" select="$pSource2"/>
            </xsl:apply-templates>
            <xsl:apply-templates
                 select="$pSource2/*/MANUFACTURER[
                                        @name = current()/@name
                                     ]/node()">
                <xsl:with-param name="pSource2" select="/"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="CAR"/>
    <xsl:template
         match="CAR[count(.|key('kCarByMan-Mod-Date',
                                concat(../@name,'+',CAR_MODEL,'+',CAR_REG_DATE)
                            )[1]
                    ) = 1]">
        <xsl:param name="pSource2"/>
        <xsl:variable
             name="vKey"
             select="concat(../@name,'+',CAR_MODEL,'+',CAR_REG_DATE)"/>
        <xsl:variable name="vGroup" select="key('kCarByMan-Mod-Date',$vKey)"/>
        <xsl:for-each select="$pSource2">
            <xsl:variable name="vGroup2"
                          select="key('kCarByMan-Mod-Date',$vKey)"/>
            <xsl:apply-templates
                 select="$vGroup[not(count($vGroup2) > count($vGroup))]"
                 mode="copy"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Output:

<DEALERSHIP reg_number="01234567">
    <MANUFACTURER name="VAUXHALL">
        <CAR>
            <CAR_VIN>12345678901234567</CAR_VIN>
            <CAR_ENG>1.9</CAR_ENG>
            <CAR_MODEL>ASTRA</CAR_MODEL>
            <CAR_REG_DATE>20040331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>HH54 RRY</CAR_REG>
            <COLOUR>RED</COLOUR>
        </CAR>
        <CAR>
            <CAR_VIN>12345678901234567</CAR_VIN>
            <CAR_ENG>2.5</CAR_ENG>
            <CAR_MODEL>CALIBRA</CAR_MODEL>
            <CAR_REG_DATE>20030331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>HH54 RRY</CAR_REG>
            <COLOUR>BLUE</COLOUR>
        </CAR>
        <CAR>
            <CAR_VIN>XXX12345678901234567</CAR_VIN>
            <CAR_ENG>1.9</CAR_ENG>
            <CAR_MODEL>ASTRA</CAR_MODEL>
            <CAR_REG_DATE>20060331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>SS00 RRY</CAR_REG>
            <COLOUR>BLUE</COLOUR>
        </CAR>
        <CAR>
            <CAR_VIN>XXX12345678901234567</CAR_VIN>
            <CAR_ENG>1.9</CAR_ENG>
            <CAR_MODEL>ASTRA</CAR_MODEL>
            <CAR_REG_DATE>20060331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>SS00 RRY</CAR_REG>
            <COLOUR>BLUE</COLOUR>
        </CAR>
    </MANUFACTURER>
    <MANUFACTURER name="FORD">
        <CAR>
            <CAR_VIN>12345678901234567</CAR_VIN>
            <CAR_ENG>2.5</CAR_ENG>
            <CAR_MODEL>CMAX</CAR_MODEL>
            <CAR_REG_DATE>20050331</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>HH54 RRY</CAR_REG>
            <COLOUR>RED</COLOUR>
        </CAR>
    </MANUFACTURER>
    <MANUFACTURER name="TOYOTA">
        <CAR>
            <CAR_VIN>XXX12345678901234567</CAR_VIN>
            <CAR_ENG>1.9</CAR_ENG>
            <CAR_MODEL>Corolla</CAR_MODEL>
            <CAR_REG_DATE>20030812</CAR_REG_DATE>
            <TRANSMISSION>A</TRANSMISSION>
            <CAR_REG>SS00 RRY</CAR_REG>
            <COLOUR>RED</COLOUR>
        </CAR>
    </MANUFACTURER>
</DEALERSHIP>

Note: Grouping by manufacturer, model and date. Traversing Data1.xml. DEALERSHIP rule (match node from Data1.xml only): copy itself, apply templates to child with Data2.xml as second source, apply templates to manufacturers from Data2.xml not present in Data1.xml. MANUFACTURER rule (match nodes from both Data1.xml and Data2.xml): copy itself, apply templates to children with pSource2 param as second source, apply templates to CAR belonging to the same manufacturer in second source (this would be empty for manufacturers from Data2.xml not present in Data1.xml). Empty CAR default rule. "First in a kind" CAR rule: copy current group if there are no more items in the same group from second source (This means that for equal number, both gets copied. Clarify behaviour if this is not desired.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文