在XSLT中,嵌套的foreach循环输出计数是两倍且相同

时间:2018-12-08 17:12:42

标签: xml xslt xpath foreach value-of

在下面的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>

我针对此xml使用的XSLT代码是。

<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 :(得分:1)

由于您随意使用//,因此您的内部说明是

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

将处理整个XML文档中的所有 r:Entries/p:root个节点。而且由于它嵌套在外部:

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

它将实例化两次,对于XML中的每个r:Entries节点一次。每个节点经过两次处理,结果节点的数量是开始时的两倍。


类似地,您:

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

选择本地名称为"LAT"的XML文档中的所有节点-在XSLT 1.0中,xsl:value-of将始终返回其中第一个的值。 / p>


值得一提的另一点:由于您已经声明了xmlns:p="test1"xmlns:r="test2"(如您所愿),因此可以使用{{ 1}}。

最后,请勿在文字结果元素就足够的地方使用*[local-name()='LAT']:例如而不是p:LATxsl:element