В XSLT количество выходных циклов вложенного цикла foreach равно двум - PullRequest
0 голосов
/ 08 декабря 2018

В приведенном ниже преобразовании xslt указан входной xml.

    <root xmlns="test1">
    <Entries xmlns="test2">
        <root xmlns="test1">
            <LAT>1</LAT>
        </root>
        <root xmlns="test1">
            <LAT>2</LAT>
        </root>
    </Entries>
    <Entries xmlns="test2">
        <root xmlns="test1">
            <LAT>3</LAT>
        </root>
        <root xmlns="test1">
            <LAT>4</LAT>
        </root>
    </Entries>
</root>

Код XSLT, который я использую для этого xml, равен.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:p="test1"
xmlns:r="test2"
                version="1.0">
  <xsl:template match="//*[local-name()='root']">
<xsl:element name="Test">
<xsl:for-each select="//p:root/r:Entries">

<xsl:variable name="i" select="position()"/>
       <xsl:for-each select="//p:root/r:Entries/p:root">
       <xsl:element name="{concat('imei', $i)}"> <xsl:element name="LAT"><xsl:value-of select="//*[local-name()='LAT']"/></xsl:element>

</xsl:element>
      </xsl:for-each>

      </xsl:for-each>
</xsl:element>
  </xsl:template> 
</xsl:stylesheet>

Требуемый результат:

<Test>
<imei1>
 <LAT>1</LAT>
</imei1>
<imei1>
 <LAT>2</LAT>
</imei1>
<imei2>
 <LAT>3</LAT>
</imei2>
<imei4>
 <LAT>4</LAT>
</imei4>
</Test>

Результат, который я получаю:

<Test>
<imei1>
    <LAT>1</LAT>
</imei1>
<imei1>
    <LAT>1</LAT>
</imei1>
<imei1>
    <LAT>1</LAT>
</imei1>
<imei1>
    <LAT>1</LAT>
</imei1>
<imei2>
    <LAT>1</LAT>
</imei2>
<imei2>
    <LAT>1</LAT>
</imei2>
<imei2>
    <LAT>1</LAT>
</imei2>
<imei2>
    <LAT>1</LAT>
</imei2>

Одно и то же значение повторяется и повторяется дважды, если я дал неправильный xpath.Первый цикл выполняется правильно дважды, как и ожидалось, что мы можем видеть в конкатенированных выражениях imei1 и imei2, но второй цикл выполняет вдвое больше ожидаемого результата и дает тот же результат.

1 Ответ

0 голосов
/ 08 декабря 2018

Из-за вашего беспорядочного использования // ваша внутренняя инструкция:

<xsl:for-each select="//p:root/r:Entries/p:root">

обработает все r:Entries/p:root узлов во всем документе XML.А так как он вложен во внешний:

<xsl:for-each select="//p:root/r:Entries">

, он будет создан дважды, один раз для каждого r:Entries узла в XML.Каждый узел, обработанный дважды, дает вдвое больше узлов, чем нужно было начинать.


Аналогично, ваш:

<xsl:value-of select="//*[local-name()='LAT']"/>

выбирает все узловв XML-документе с локальным именем "LAT" - и в XSLT 1.0 xsl:value-of всегда будет возвращать значение первого из них.


Еще один момент, о котором стоит упомянуть: поскольку вы объявилии xmlns:p="test1" и xmlns:r="test2" (как вам следует), нет необходимости использовать хаки, такие как *[local-name()='LAT'], когда вы можете использовать p:LAT.

Наконец, не используйте xsl:element, гдеДостаточно буквального элемента результата: например, вместо <xsl:element name="Test"> напишите <Test>.

...