XSL 1.0 Различается через Munchian и несколько режимов матча - PullRequest
1 голос
/ 06 августа 2010

Изучение XSL, переведенного в это время в XSL 1.0, с попыткой создать отдельный набор, а также выполнить последующий проход, используя конструкции режимов соответствия.

Если режимы не введены, все хорошо.

Как только режимы введены, перевод не выполняется.

Любая помощь будет оценена.

Примерный xml:

    <?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <node>
        <category comat="0" catat="AC1" catatt="AD1">C1</category>
        <desc>D1</desc>
    </node>
    <node>
        <category comat="0" catat="AC2" catatt="AD2">C2</category>
        <desc>D2</desc>
    </node>
    <node>
        <category comat="0" catat="AC1" catatt="AD1">C1</category>
        <desc>D1</desc>
    </node>
    <node>
        <category comat="0" catat="AC3" catatt="AD3">C3</category>
        <desc>D3</desc>
    </node>
</dataset>

Образец Munchian производит отдельные записи.

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/><!-- New document created with EditiX at Thu Aug 05 16:51:01 PDT 2010 -->
    <xsl:key name="nodekey" match="node/category" use="concat(@catat,'_',@catatt)"/>
    <xsl:template match="dataset">
        <CAT>
            <xsl:apply-templates />
        </CAT>
    </xsl:template>
    <xsl:template match="dataset" >
        <CATD>
            <xsl:for-each select="node/category[generate-id()= generate-id(key('nodekey',concat(@catat,'_',@catatt))[1])]">
                <CAT_D>
                    <xsl:value-of select="concat(@catat,'_',@catatt)"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="."/>
                </CAT_D>
            </xsl:for-each>
        </CATD>
    </xsl:template>
</xsl:stylesheet>

Пример вывода:

<?xml version="1.0" encoding="UTF-8"?>
<CATD xmlns:exslt="http://exslt.org/common">
   <CAT_D>AC1_AD1_C1</CAT_D>
   <CAT_D>AC2_AD2_C2</CAT_D>
   <CAT_D>AC3_AD3_C3</CAT_D>
</CATD>

Однако, когда добавляются режимы, переводы не выполняются?

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/><!-- New document created with EditiX at Thu Aug 05 16:51:01 PDT 2010 -->
    <xsl:key name="nodekey" match="node/category" use="concat(@catat,'_',@catatt)"/>
    <xsl:template match="dataset">
        <UCAT>
            <xsl:apply-templates mode="ucatmode"/>
        </UCAT>
        <DCAT>
            <xsl:apply-templates mode="catmode"/>
        </DCAT>
    </xsl:template>
    <xsl:template match="dataset" mode="ucatmode">
        <DESC>
            <xsl:for-each select="node/category[generate-id()= generate-id(key('nodekey',concat(@catat,'_',@catatt))[1])]">
                <CAT_D>
                    <xsl:value-of select="concat(@catat,'_',@catatt)"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="."/>
                </CAT_D>
            </xsl:for-each>
        </DESC>
    </xsl:template>
    <xsl:template match="dataset/node/desc" mode="catmode">
        <CATQ>
            <xsl:value-of select="."/>
        </CATQ>
    </xsl:template>
</xsl:stylesheet>

Ответы [ 2 ]

2 голосов
/ 06 августа 2010

Однако, когда режимы добавляются одинаково перевод не выполнен?

Ваша проблема в этом коде :

<xsl:template match="dataset">
    <UCAT>
        <xsl:apply-templates mode="ucatmode"/>
    </UCAT>
    <DCAT>
        <xsl:apply-templates mode="catmode"/>
    </DCAT>
</xsl:template>

<xsl:template match="dataset" mode="ucatmode">

Инструкция выше:

<xsl:apply-templates mode="ucatmode"/>

является сокращением от;

<xsl:apply-templates select="child::node()"
     mode="ucatmode"/>

Однако потомками элемента dataset являются только элементы с именем node и текстовые узлы только для пробелов. В вашем коде нет шаблона, который находится в режиме с именем ucatmode и соответствует элементу node.

Следовательно, для обработки не выбран ни один шаблон, и процессор XSLT использует встроенные шаблоны (они доступны для любого режима). Встроенные шаблоны XSLT вызывают копирование всех текстовых узлов - и это то, что вы получаете.

Точно такая же проблема существует с инструкцией :

<xsl:apply-templates mode="catmode"/>

Решение : Заменить:

<xsl:template match="dataset">
    <UCAT>
        <xsl:apply-templates mode="ucatmode"/>
    </UCAT>
    <DCAT>
        <xsl:apply-templates mode="catmode"/>
    </DCAT>
</xsl:template>

с

<xsl:template match="/">
    <UCAT>
        <xsl:apply-templates mode="ucatmode"/>
    </UCAT>
    <DCAT>
        <xsl:apply-templates mode="catmode"/>
    </DCAT>
</xsl:template>

Этот шаблон теперь соответствует узлу документа, его единственным (верхним) дочерним элементом является элемент dataset, и теперь для обработки будут выбраны два измененных шаблона, соответствующие dataset.

Вам все еще нужно заменить:

<xsl:apply-templates mode="catmode"/>

с:

    <xsl:apply-templates mode="catmode"
         select="dataset/node/desc"/>

, поскольку desc не является потомком dataset и встроенная обработка шаблона будет снова задействована для всех потомков dataset, за исключением desc.

Одно незначительное дополнительное исправление заключается в устранении всех текстовых узлов, содержащих только пробелы, - это может быть легко достигнуто с помощью следующей инструкции XSLT:

<xsl:strip-space elements="*"/>

Еще одно незначительное улучшение - предотвращение появления префикса exslt: с каждым элементом буквального результата. Это достигается добавлением атрибута:

exclude-result-prefixes="exslt"

до <xsl:stylesheet> инструкции.

Таким образом, полное исправленное преобразование (с соответствующим отступом для удобства чтения) составляет :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:exslt="http://exslt.org/common"
 exclude-result-prefixes="exslt"
 >
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="nodekey" match="node/category"
    use="concat(@catat,'_',@catatt)"/>

    <xsl:template match="/">
        <UCAT>
            <xsl:apply-templates mode="ucatmode"/>
        </UCAT>
        <DCAT>
            <xsl:apply-templates mode="catmode"
                 select="dataset/node/desc"/>
        </DCAT>
    </xsl:template>

    <xsl:template match="dataset" mode="ucatmode">
        <DESC>
            <xsl:for-each select=
             "node/category
                   [generate-id()
                   =
                    generate-id(key('nodekey',
                                     concat(@catat,'_',@catatt)
                                     )[1]
                                )
                    ]">
                <CAT_D>
                    <xsl:value-of select="concat(@catat,'_',@catatt)"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="."/>
                </CAT_D>
            </xsl:for-each>
        </DESC>
    </xsl:template>

    <xsl:template match="dataset/node/desc" mode="catmode">
        <CATQ>
            <xsl:value-of select="."/>
        </CATQ>
    </xsl:template>
</xsl:stylesheet>

Когда он применяется к предоставленному документу XML :

<dataset>
    <node>
        <category comat="0" catat="AC1" catatt="AD1">C1</category>
        <desc>D1</desc>
    </node>
    <node>
        <category comat="0" catat="AC2" catatt="AD2">C2</category>
        <desc>D2</desc>
    </node>
    <node>
        <category comat="0" catat="AC1" catatt="AD1">C1</category>
        <desc>D1</desc>
    </node>
    <node>
        <category comat="0" catat="AC3" catatt="AD3">C3</category>
        <desc>D3</desc>
    </node>
</dataset>

желаемый, правильный результат выдается :

<UCAT>
   <DESC>
      <CAT_D>AC1_AD1_C1</CAT_D>
      <CAT_D>AC2_AD2_C2</CAT_D>
      <CAT_D>AC3_AD3_C3</CAT_D>
   </DESC>
</UCAT>
<DCAT>
   <CATQ>D1</CATQ>
   <CATQ>D2</CATQ>
   <CATQ>D1</CATQ>
   <CATQ>D3</CATQ>
</DCAT>
0 голосов
/ 07 августа 2010

Спасибо, Димитр, ваши предложения работали так, как описано.

Добавление формального решения для справки.

<?xml version="1.0" encoding="ISO-8859-1"?>
  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exslt" >
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="distinct-CompositeKeyNOS" match="Downloads/Download[@ParentDownloadID='0']" use="concat(@Version,'_',@DownloadType,'_',@Name,'_',@IsBeta)"/>
<xsl:template match="/">
<NotifiusExportData>

            <xsl:apply-templates mode="OSAgnostic">
    </xsl:apply-templates> 

            <xsl:apply-templates mode="english">
    </xsl:apply-templates> 

            <xsl:apply-templates mode="DevicesLangCodes">
    </xsl:apply-templates> 
</NotifiusExportData>
</xsl:template>



    <xsl:template match="NotifiusExportData" mode="OSAgnostic">

        <xsl:for-each select="Downloads/Download[generate-id()= generate-id(key('distinct-CompositeKeyNOS',concat(@Version,'_',@DownloadType,'_',@Name,'_',@IsBeta))[1])]">
                <xsl:sort select="@Version" order="descending" data-type="number"/>
                <xsl:sort select="@DownloadType" order="ascending"/>
                <xsl:sort select="@Name" order="ascending"/>
                <xsl:sort select="@OS" order="descending" data-type="number"/>
                <xsl:sort select="@Is64Bit" order="descending" data-type="number"/>
                <xsl:sort select="@IsBeta" order="ascending" data-type="number"/>
            <Downloads>
                <CompositeKeyNOS>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </CompositeKeyNOS>
                <CompositeKey>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Is64Bit"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </CompositeKey>
                <ParentDownloadID>
                    <xsl:value-of select="@ParentDownloadID"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </ParentDownloadID>
                <DownloadId>
                    <xsl:value-of select="@DownloadId"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </DownloadId>
                <Release>
                    <xsl:value-of select="@Release"/>
                </Release>
                <Version>
                    <xsl:value-of select="@Version"/>
                </Version>
                <DetailsURL>
                    <xsl:value-of select="@DetailsURL"/>
                </DetailsURL>
                <IsBeta>
                    <xsl:value-of select="@IsBeta"/>
                </IsBeta>
                <ReleaseDate>
                    <xsl:value-of select="@ReleaseDate"/>
                </ReleaseDate>
                <DownloadType>
                    <xsl:value-of select="@DownloadType"/>
                </DownloadType>
                <OS>
                    <xsl:value-of select="@OS"/>
                </OS>
                <Is64Bit>
                    <xsl:value-of select="@Is64Bit"/>
                </Is64Bit>
                <LangCode5>
                    <xsl:value-of select="@LangCode5"/>
                </LangCode5>
                <Name>
                    <xsl:value-of select="@Name"/>
                </Name>
                <GraphicsVersion>
                    <xsl:value-of select="@GraphicsVersion"/>
                </GraphicsVersion>
                <USBEmitterVersion>
                    <xsl:value-of select="@USBEmitterVersion"/>
                </USBEmitterVersion>
            </Downloads>

        </xsl:for-each>

    </xsl:template>


    <xsl:template match="NotifiusExportData/Downloads" mode="english"><!-- xsl:for-each select="." --><!--xsl:if test="@ParentDownloadID=0"-->
        <xsl:for-each select="Download[@ParentDownloadID='0']">
            <xsl:sort select="@Version" order="descending" data-type="number"/>
            <xsl:sort select="@DownloadType" order="ascending"/>
            <xsl:sort select="@Name" order="ascending"/>
            <xsl:sort select="@OS" order="descending" data-type="number"/>
            <xsl:sort select="@Is64Bit" order="descending" data-type="number"/>
            <xsl:sort select="@IsBeta" order="ascending" data-type="number"/>
            <NDownloads>
                <NCompositeKeyNOS>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </NCompositeKeyNOS>
                <NCompositeKey>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Is64Bit"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </NCompositeKey>
                <ParentDownloadID>
                    <xsl:value-of select="@ParentDownloadID"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </ParentDownloadID>
                <DownloadId>
                    <xsl:value-of select="@DownloadId"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </DownloadId>
                <Release>
                    <xsl:value-of select="@Release"/>
                </Release>
                <Version>
                    <xsl:value-of select="@Version"/>
                </Version>
                <DetailsURL>
                    <xsl:value-of select="@DetailsURL"/>
                </DetailsURL>
                <IsBeta>
                    <xsl:value-of select="@IsBeta"/>
                </IsBeta>
                <ReleaseDate>
                    <xsl:value-of select="@ReleaseDate"/>
                </ReleaseDate>
                <DownloadType>
                    <xsl:value-of select="@DownloadType"/>
                </DownloadType>
                <OS>
                    <xsl:value-of select="@OS"/>
                </OS>
                <Is64Bit>
                    <xsl:value-of select="@Is64Bit"/>
                </Is64Bit>
                <LangCode5>
                    <xsl:value-of select="@LangCode5"/>
                </LangCode5>
                <Name>
                    <xsl:value-of select="@Name"/>
                </Name>
                <GraphicsVersion>
                    <xsl:value-of select="@GraphicsVersion"/>
                </GraphicsVersion>
                <USBEmitterVersion>
                    <xsl:value-of select="@USBEmitterVersion"/>
                </USBEmitterVersion>
            </NDownloads><!--/xsl:if --><!-- /xsl:for-each -->
        </xsl:for-each>
    </xsl:template><!-- xsl:template match="Download" mode="DevicesLangCodes" -->



<!-- xsl:template match="Download" mode="DevicesLangCodes" -->

    <xsl:template match="NotifiusExportData/Downloads" mode="DevicesLangCodes"><!-- xsl:for-each select="." --><!-- xsl:if test="@ParentDownloadID!=0" -->
        <xsl:for-each select="Download">
            <xsl:sort select="@Version" order="descending" data-type="number"/>
            <xsl:sort select="@DownloadType" order="ascending"/>
            <xsl:sort select="@Name" order="ascending"/>
            <xsl:sort select="@LangCode5" order="ascending"/>
            <xsl:sort select="@OS" order="descending" data-type="number"/>
            <xsl:sort select="@Is64Bit" order="descending" data-type="number"/>
            <xsl:sort select="@IsBeta" order="ascending" data-type="number"/>
            <NNDownloads>
                <NNCompositeKeyNOS>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </NNCompositeKeyNOS>
                <NNCompositeKey>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Is64Bit"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </NNCompositeKey>
                <NParentDownloadID>
                    <xsl:value-of select="@ParentDownloadID"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </NParentDownloadID>
                <NDownloadId>
                    <xsl:value-of select="@DownloadId"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </NDownloadId>
                <NLangCode5>
                    <xsl:value-of select="@LangCode5"/>
                </NLangCode5>
                <xsl:call-template name="groupLangCodes"/>
                <xsl:call-template name="groupDeviceIds"/>
            </NNDownloads>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="groupLangCodes" match="LangCodes">
        <LangCodes>
            <xsl:call-template name="getLangCodeIds"/>
        </LangCodes>
    </xsl:template>
    <xsl:template name="groupDeviceIds" match="DeviceIds">
        <DeviceIds>
            <xsl:call-template name="getDeviceIds"/>
        </DeviceIds>
    </xsl:template>
    <xsl:template name="getLangCodeIds">
        <xsl:for-each select="LangCodes/LangCode">
            <xsl:value-of select="@Id"/>
            <xsl:text> </xsl:text>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="getDeviceIds">
        <xsl:for-each select="DeviceIds/DeviceId">
            <xsl:value-of select="@Id"/>
            <xsl:text> </xsl:text>
        </xsl:for-each>
    </xsl:template>

  </xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...