繁体   English   中英

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

[英]Complete xslt newbie. How do I merge these 2 xml sources in xslt version 1.0. applying grouping and sorting?

转化源

数据1.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进行调出。

它的xsl逻辑和代码与我刚接触的合并特别相关,需要一些帮助。

合并逻辑将数据源MANUFACTURERS和子元素组合在一起。 如果两个源都具有相同的CAR元素,并且其子元素CAR_REG_DATE和CAR_MODEL的内容相同,则仅包含Data1.xml或Data2.xml中的数据,以该唯一组合的最高计数为准。 如果组合在两个数据源中具有相同数量的数据,则使用转换源xml,在上述情况下为Data1.xml。 生成的元素需要按CAR_REG_DATE在每个MANUFATURER元素中降序排列。 因此,在以上数据示例中,您可以看到必要的输出包括所有MANUFACTURERS; 沃克斯豪尔,福特,丰田。 对于Vauxhall Astra 20060331,输出包含Data2.xml ASTRA 20060331中的数据,但不包括Data1.xml中的相同数据组合。所有其他Vauxhall Astra(非20060331)的情况都包含在Data1.xml的输出中。由CAR_REG_DATE降序排列的Ford Manaufacturer数据降序的每个MANUFACTURER都包含在Data1排序的CAR_REG_DATE desc的输出中。 Toyota Manaufacturer数据包含在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中的组合。 同样(当我考虑到这一点),当相同的组合CAR_REG_DATE和CAR_MODEL在DATA1.xml中时,它将始终从Data2.xsml中排除数据,而不管这两个数据源中的计数如何,这绝对不是我想要的。

应用stylesheet.xsl的结果

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

12345678901234567 1.9 ASTRA 20060331 A HH54 RRY红色12345678901234567 1.9 ASTRA 20040331 A HH54 RRY红色12345678901234567 2.5 CALIBRA 20030331 A HH54 RRY蓝色12345678901234567 2.5 CMAX 20050331 A HH54 RRY红色

后来我想到了将源文档和外部文档都合并到局部变量中,然后将合并的MANUFACTURER传递到模板中并遍历每个CAR元素的想法。 我可以通过以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唯一组合。 一旦合并,在每个MANUFACTURER中降序的CAR_REG_DATE

因此,选择沃克斯豪尔制造商

Astra- 20060331的唯一组合-Data1.xml具有1和Data2.xml具有2。

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

迪米我非常感谢您的评论。 我认为这是我的问题; 我试图查看问题并将其分解为较小的部分,但在这里失败了。 发现xsl:variable是不可变的,我仍然感到震惊。 (或者看起来)。

此样式表:

<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.xml DEALERSHIP规则(从匹配节点Data1.xml唯一的):自我复制,具有应用模板儿童Data2.xml作为第二个来源,从应用模板厂家Data2.xml不存在Data1.xml MANUFACTURER规则(匹配来自Data1.xmlData2.xml节点):复制自身,将模板应用到具有pSource2参数作为第二个源的子级,将模板应用到第二个源中属于同一制造商的CAR (对于来自Data2.xml不存在Data1.xml )。 CAR默认规则。 “第一种” CAR规则:如果第二个来源的同一组中没有更多项目,则复制当前组(这意味着对于相同数量的项目,两个都将被复制。 如果不需要,请澄清行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM