【问题标题】:Display a value from a preceding-sibling of a following sibling/child node?显示来自后续兄弟/子节点的前兄弟的值?
【发布时间】:2013-12-26 22:02:50
【问题描述】:

基于此 XML,我试图显示一个表,其中每个 DOCREF 都有一行,该表还显示了 REFERENCE 等于 ID 的 STEP2/TITLE。我可以在 DOCREF/@REFERENCE = STEP2/@ID 的情况下进行这项工作,但我遇到麻烦的地方是已经要求 STEP2/TITLE 也显示每个 STEP3 元素,直到有一个新的 STEP2 元素,然后它会显示所有的 STEP3,直到它再次改变等等。

<WORKCARD>
  <STSBODY>
    <DOCREFS>
      <DOCREF REFERENCE="123" VALUE="Ref1"/>        
      <DOCREF REFERENCE="456" VALUE="Ref2"/>
      <DOCREF REFERENCE="789" VALUE="Ref3"/>
    </DOCREFS>
  </STSBODY>
  <BODY>
    <ITEMS>
      <ITEM>
        <XML>
          <STEP2 ID="123">
            <TITLE>Test1</TITLE>
          </STEP2>
        </XML>
      </ITEM>
      <ITEM>
        <ITEMXML>
          <XML>
            <STEP3 ID=456>Step info goes here</STEP3>
          </XML>
        </ITEMXML>
      </ITEM>
      <ITEM>
        <ITEMXML>
          <XML>
            <STEP2 ID=789>Test2</STEP3>
          </XML>
        </ITEMXML>
      </ITEM>
    </ITEMS>
  </BODY>
</WORKCARD>

我正在修改现有的 XSLT。这是我正在使用的部分,你可以看到我的各种尝试都没有得到我需要的东西。

<xsl:key name="step2Ref" match="STEP2" use="@ID" />

<xsl:when test="DOCREF[@TASK_CARD_ITEM > $item]">
  <xsl:for-each select="DOCREF[@TASK_CARD_ITEM > $item and not($doctype = 'NDT' and key('refItem', @TASK_CARD_ITEM)/descendant::L1ITEM[@ID] and not(key('refItem',@TASK_CARD_ITEM)/descendant::L2ITEM))]">
    <xsl:sort select="@TASK_CARD_ITEM" data-type="number" />
    <!--<xsl:call-template name="subtaskitemrow"/>-->

    <fo:table-row>
      <fo:table-cell number-columns-spanned="6" border="solid 1pt red">
        <fo:block>
          <!-- this displays the correct info when there is a matching STEP2/@ID-->              
          <xsl:value-of select="key('step2Ref', @REFERENCE)/TITLE" />***                  
          <!--This gets the STEP2/TITLE where STEP2/@ID = @REFERENCE-->
          <xsl:value-of select="//STEP2/@ID" />+++
          <xsl:value-of select="//ITEM/@TASK_CARD_ITEM" />***
          <xsl:value-of select="@TASK_CARD_ITEM"/>+++
          <xsl:variable name="tcitem"><xsl:value-of select="@TASK_CARD_ITEM" /></xsl:variable>
          <xsl:value-of select="//ITEM[$tcitem]/@TASK_CARD_ITEM" />***
          <!--preceding-sibling STEP2/@ID-->
        </fo:block>
      </fo:table-cell>
  </fo:table-row>        
  </xsl:for-each>    
</xsl:when>  

我给自己写的一些笔记是:

  • 循环遍历 DOCREFS 时,我需要显示每个文档的 STEP2/TITLE,直到 STEP2/TITLE 更改,然后显示新的。
  • 我需要匹配STEP3的前兄弟STEP2的@ID

请帮忙?

预计到达时间:

此示例的所需输出(xml 中的文本与原始帖子略有不同)将是这样的:

  1. 测试1
  2. 测试1
  3. 测试2

因此,对于第一个和第二个 DOCREF,它将显示来自第一个 STEP2 的标题,而第三个 DOCREF 将显示来自第二个 STEP2 的标题。

【问题讨论】:

  • 你能包含一些想要的输出吗?另外:&lt;fo:block&gt; 中带有前缀//select 语句看起来有点可疑,因为它们基本上扫描整个 文档而与上下文无关。这就是你想要的吗?
  • 您好,感谢您的回复! // 是我绝望的尝试,因为我变得相当沮丧:( 我将在原始问题中添加所需的输出。谢谢!

标签: xslt xpath


【解决方案1】:

您的 XML 文档格式不正确,而且 - 更重要的是 - 第二个 &lt;STEP2&gt; 没有 &lt;TITLE&gt;。假设它可以更正为:

<WORKCARD>
  <STSBODY>
    <DOCREFS>
      <DOCREF REFERENCE="123" VALUE="Ref1"/>        
      <DOCREF REFERENCE="456" VALUE="Ref2"/>
      <DOCREF REFERENCE="789" VALUE="Ref3"/>
    </DOCREFS>
  </STSBODY>
  <BODY>
    <ITEMS>
      <ITEM>
        <XML>
          <STEP2 ID="123">
            <TITLE>Test1</TITLE>
          </STEP2>
        </XML>
      </ITEM>
      <ITEM>
        <ITEMXML>
          <XML>
            <STEP3 ID="456">Step info goes here</STEP3>
          </XML>
        </ITEMXML>
      </ITEM>
      <ITEM>
        <ITEMXML>
          <XML>
            <STEP2 ID="789">
                <TITLE>Test2</TITLE>
            </STEP2>
          </XML>
        </ITEMXML>
      </ITEM>
    </ITEMS>
  </BODY>
</WORKCARD>

您可以使用以下逻辑来检索您需要的数据(出于测试目的,您的问题中显示的数据多于要求的数据):

<xsl:key name="step2Ref" match="STEP2" use="@ID" />
...
<xsl:template match="DOCREF">
<tr>
    <!-- DOCREF VALUE-->
    <td><xsl:value-of select="@VALUE" /></td>
    <!-- DOCREF REFERENCE -->
    <td><xsl:value-of select="@REFERENCE" /></td>

    <xsl:variable name="ref">
        <xsl:choose>
            <xsl:when test="key('step2Ref', @REFERENCE)">
                <xsl:value-of select="@REFERENCE" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="preceding-sibling::DOCREF[key('step2Ref', @REFERENCE)][1]/@REFERENCE" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <!-- REFERENCE USED FOR KEY -->
    <td><xsl:value-of select="$ref" /></td>
    <!-- RETRIEVED TITLE -->
    <td><xsl:value-of select="key('step2Ref', $ref)/TITLE" /></td>
</tr>
</xsl:template>

在上面的例子中,返回如下结果:

Ref1    123 123 Test1
Ref2    456 123 Test1
Ref3    789 789 Test2

请注意,假设第一个&lt;DOCREF&gt;确实有一个相关的&lt;STEP2&gt;

【讨论】:

  • 成功了!太感谢了。现在再想出一个你所提供的应该帮助的部分:)
猜你喜欢
  • 2014-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-20
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多