Полный xslt новичок.Как мне объединить эти 2 источника XML в XSLT версии 1.0.применять группировку и сортировку? - PullRequest
1 голос
/ 27 января 2011

Источник преобразования

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.

Как вы можете видеть из таблицы стилей, я должен включить Data2.xml через вызов некоторой обработки Java.Я использовал 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.Таким образом, в приведенном выше примере данных вы можете видеть, что необходимый вывод включает в себя всех ПРОИЗВОДИТЕЛЕЙ;VAUXHALL, FORD, TOYOTA.В случае Vauxhall Astra 20060331 выходные данные содержат данные из Data2.xml ASTRA 20060331, исключая ту же комбинацию данных из Data1.xml. Все остальные случаи Vauxhall Astra (не 20060331) включаются в выходной файл из Data1.xml всех CARS вкаждый MANUFACTURER, упорядоченный по CAR_REG_DATE по убыванию данных Ford Manaufacturer, включается в выходные данные из Data1 упорядоченного CAR_REG_DATE desc.Данные Toyota Manaufacturer включены в выходные данные из Data2, упорядоченного CAR_REG_DATE desc.

. Сначала мне пришла в голову идея объединения с использованием оператора объединения, в котором значение содержимого Data2.xml CAR_REG_DATE и CAR_MODEL не совпадает с Data1.xml.CAR_REG_DATE, но это исключило бы любые данные из Data2.xml, когда в Data1.xml не было совпадения данных CAR_REG_DATE и CAR_MODEL.Кроме того (когда я думал об этом), он всегда будет исключать данные из Data2.xsml, когда одна и та же комбинация CAR_REG_DATE и CAR_MODEL была в DATA1.xml независимо от количества в любом источнике данных, что, безусловно, не то, что я хочу.

Результат от применения stylesheet.xsl

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

12345678901234567 1.9 ASTRA 20060331 A HH54 КРАСНЫЙ КРАСНЫЙ 12345678901234567 1.9 ASTRA 20040331 A HH54 КРАСНЫЙ КРАСНЫЙ 12345678901234567 2.5 КАЛИБРА 20030331 A HRA 4567 R6767*

Когда мне пришла в голову идея объединить исходный документ и внешний документ вместе в локальную переменную и передать этот объединенный ИЗГОТОВИТЕЛЬ в шаблон и выполнить цикл по каждому элементу CAR.Я могу различать элементы CAR Data1.xml и Data2.xml по содержанию CAR_VIN, начиная с XXX. Поэтому я подумал, что я буду циклически проходить через каждый объединенный элемент CAR и выбирать счетчики для исходного документа и внешнего документа и включать внешний или исключать источник на основерезультат.

Возможно ли это и как мне поступить, или есть правильный способ сделать это, помня, что я новичок в обработке xslt?

Любая помощь в решении этой проблемы будет очень признательна..

Привет, спасибо за ответ

Я отредактировал набор данных, чтобы избежать rsi.

В двух словах мне нужно реализовать следующеелогика -

В зависимости от того, какой источник Data1.xml или Data2.xml имеет большее число уникальных комбинаций, CAR_REG_DATE и CAR_MODEL (в пределах CAR) включают источники данных в выводе - исключают данные других источников с той же комбинацией.

Все уникальные комбинации CAR_REG_DATE - CAR_MODEL должны быть включены из обоих источников.Заказал CAR_REG_DATE по убыванию в каждом MANUFACTURER, после объединения

Итак, взяв Vauxhall MANUFACTURER

уникальную комбинацию Astra- 20060331 - Data1.xml имеет 1, а Data2.xml имеет 2.

Мне нужно вывести Astras 20060331 из набора Data2.xml для этой комбинации и игнорировать Data1.xml Astras 20060331 1 вхождение, как показано в requiredoutput.xml выше

Дими Я действительно ценю ваш комментарий.Я думаю, что это моя проблема;Я пытаюсь посмотреть на проблему и разбить ее на более мелкие кусочки, но у меня ничего не получается.Я все еще в шоке, обнаружив, что переменная xsl: неизменна.(или так кажется).

1 Ответ

0 голосов
/ 28 января 2011

Эта таблица стилей:

<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.xml и Data2.xml): скопируйте себя, примените шаблоны к дочерним элементам с параметром pSource2 в качестве второго источника, примените шаблоны к CAR, принадлежащему тому же производителю во втором источнике (этобудет пустым для производителей из Data2.xml, отсутствующих в Data1.xml).Пустое CAR правило по умолчанию.«Первое в своем роде» CAR правило: копировать текущую группу, если в той же группе больше нет элементов из второго источника (это означает, что при одинаковом количестве копируются оба. Уточнить поведение, если это нежелательно.)

...