XML - 在'for-each'中设置变量以在下一次迭代中使用

时间:2017-11-02 12:05:18

标签: xml xslt

我有一些XML数据(客户数据,所以任意的例子:)

 <attributes>
          <attribute>
            <attribute_type xsi:type="xsd:string">
              parent
            </attribute_type>
            <attribute_id xsi:type="xsd:string">
              ABC123
            </attribute_id>
            <someValue xsi:type="xsd:string">
              123456
            </someValue>
          </attribute>

          <attribute>
            <attribute_type xsi:type="xsd:string">
              child
            </attribute_type>
            <attribute_id xsi:type="xsd:string">
              ABC123
            </attribute_id>
            <someValue xsi:type="xsd:string">
              null
            </someValue>
          </attribute>
</attributes>

每个attribute都有一个“父”和“子”,它们不是嵌套的,而是包含一个标识符,用于提供两者之间的通用性。每个父母都应该跟着孩子,所以这些应该总是按顺序。

导入数据时,我只想导入'child',但父项包含我要与子项导入的信息(在本例中为someValue)。

我尝试在迭代时设置一个变量,以便它可以向前传递一个值,即:

<xsl:for-each select="attributes/attribute">
<xsl:if test="attribute_type = 'parent' ">
    <xsl:variable name="testId" select="normalize-space(attribute_id)"/> 
    <xsl:variable name="testValue" select="normalize-space(someValue)"/>   
</xsl:if>

<xsl:if test="attribute_type != 'parent' ">
attribute.<xsl:value-of select="position()"/>.id=<xsl:value-of select="normalize-space(attribute_id)"/>

    <xsl:if test="attribute_id = $testId">
        attribute.<xsl:value-of select="position()"/>.Value=<xsl:value-of select="$testValue"/>
    </xsl:if>
</xsl:for-each>

显然有很多数据和这里缺少值,但我已经减少了这一点,以保持其可读性。本质上,我只想输出'子'值,但我想通过变量将父值传递给子的输出。

预期输出为:

  attribute.2.id    = ABC123
  attribute.2.Value = 123456

(由于迭代,我预计第一个position()为'2'但第一个parent未输出为position() = 1

以上不起作用,我认为可能与变量范围有关。

position()使得简单地“输出”数据变得困难,除非我用<xsl:value-of select="position()+1"/>类型的东西试图将其推向前方,但我不是确定它会变得强大或可靠。

这是否可行(因为我无法修改原始XML数据)?

1 个答案:

答案 0 :(得分:1)

如果您有交叉引用,请使用key来关注并访问该值:

<xsl:key name="parent" match="attribute[normalize-space(attribute_type) = 'parent']" use="normalize-space(attribute_id)"/>

<xsl:template match="/">
  <xsl:for-each select="attributes/attribute[normalize-space(attribute_type) != 'parent']">
      attribute.<xsl:number/>.id=<xsl:value-of select="normalize-space(attribute_id)"/>
      <xsl:if test="key('parent', normalize-space(attribute_id))">
          attribute.<xsl:number/>.Value=<xsl:value-of select="normalize-space(key('parent', normalize-space(attribute_id))/someValue)"/>
      </xsl:if>
  </xsl:for-each>
</xsl:template>

另一种方法是从preceding-sibling::attribute[1][normalize-space(attribute_id) = normalize-space(current()/attribute_id)]内导航到for-each

如果你真的想要一个构造来&#34;迭代&#34;按顺序存储每个步骤的变量,然后移到XSLT 3和xsl:iteratehttps://www.w3.org/TR/xslt/#iterate)。