Xslt xsl“following”返回的不是预期的结果

Xslt xsl“following”返回的不是预期的结果,xslt,xpath,Xslt,Xpath,我有这样的xml: <ROWSET> <ROW> <FLD1>P2</FLD1> <S_VAL>1</S_VAL> <FLD2>N2</FLD2> </ROW> <ROW> <FLD1>P3</FLD1> <S_VAL>2</S_VAL>

我有这样的xml:

  <ROWSET>
    <ROW>
      <FLD1>P2</FLD1>
      <S_VAL>1</S_VAL>    
      <FLD2>N2</FLD2>
    </ROW>
    <ROW>
      <FLD1>P3</FLD1>
      <S_VAL>2</S_VAL> 
      <FLD2>N2</FLD2>    
    </ROW>
     <ROW>
      <FLD1>P3</FLD1>
      <S_VAL>3</S_VAL> 
      <FLD2>N2</FLD2>    
    </ROW>
    <ROW>
      <FLD1>P4</FLD1>
      <S_VAL>4</S_VAL>    
       <FLD2>N3</FLD2>
    </ROW>
    <ROW>
      <FLD1>P2</FLD1>
      <S_VAL>5</S_VAL>    
      <FLD2>N3</FLD2>
    </ROW>
  </ROWSET>
我的xsl中有两个变量:

  <xsl:variable name="only_need" select="/ROWSET/ROW[./FLD2='N2']"/>
  <xsl:variable name="only_need2" select="$only_need/FLD1[not(.=following::FLD1)]"/>
在名为only的变量中,我需要接收1、2、3中带有S_Val的记录。 但在名为_need2的变量中,我只收到FLD1=P3。 为什么第二个变量receve only FLD1=P3?

only_need2包含only_need中那些行的FLD1子行,这些行的值不同于整个文档中所有后续FLD1元素的值,而不仅仅是only_need2。所以你没有得到P2,因为第五排后面还有一个P2

如果您想要的实际上是每个不同FLD1值所需的最后一行,那么可以使用一个键

<xsl:key name="key_only_need2" match="/ROWSET/ROW[FLD2='N2']/FLD1" use="." />
<xsl:variable name="only_need2" select="$only_need/FLD1[
      generate-id() = generate-id( key('key_only_need2', .)[last()] )]" />

我在这里所做的是定义一个键,它将从FLD2为N2的行中提取所有FLD1元素,并根据它们的FLD1值对它们进行分组。变量声明中的谓词使用此键仅从每个组中选择最后一个元素。

这回答了您对Ian Roberts的正确答案的评论中的问题:

你能告诉我,我怎样才能只为你的需要使用下面的内容

事实上,这是一个纯粹的XPath问题

在查找不同的元素时,可以避免使用键,而只使用轴(如前面或后面),但是请记住,与使用键相比,^2上的速度非常慢:


谢谢你能告诉我,我怎样才能只为你的需要而使用下面的内容呢。感谢您的详细回答。只有10-15条记录将以$vOnlyNeed为单位。一切都像你一样。但并不完全清楚过滤器是如何工作的`[count.|$vOnlyNeed=count$vOnlyNeed]`诀窍是XPath在节点集上工作,因此当您使用exprA构建联合时,两个表达式匹配的exprB节点只计数一次。因此,[count.|$vOnlyNeed=count$vOnlyNeed]当且仅当所讨论的节点为真时才为真。是集合$vOnlyNeed的成员。
 <xsl:variable name="vOnlyNeed" select="/*/*[FLD2='N2']"/>
 <xsl:variable name="vOnlyNeedDistinct" select=
  "$vOnlyNeed
   [not(FLD1
       =
        following::*
           [count(.|$vOnlyNeed) = count($vOnlyNeed)]
             /FLD1)]
   "/>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vOnlyNeed" select="/*/*[FLD2='N2']"/>
 <xsl:variable name="vOnlyNeedDistinct" select=
  "$vOnlyNeed
   [not(FLD1
       =
        following::*
           [count(.|$vOnlyNeed) = count($vOnlyNeed)]
             /FLD1)]
   "/>

 <xsl:template match="/">
     <xsl:copy-of select="$vOnlyNeedDistinct"/>
 </xsl:template>
</xsl:stylesheet>
<ROWSET>
    <ROW>
        <FLD1>P2</FLD1>
        <S_VAL>1</S_VAL>
        <FLD2>N2</FLD2>
    </ROW>
    <ROW>
        <FLD1>P3</FLD1>
        <S_VAL>2</S_VAL>
        <FLD2>N2</FLD2>
    </ROW>
    <ROW>
        <FLD1>P3</FLD1>
        <S_VAL>3</S_VAL>
        <FLD2>N2</FLD2>
    </ROW>
    <ROW>
        <FLD1>P4</FLD1>
        <S_VAL>4</S_VAL>
        <FLD2>N3</FLD2>
    </ROW>
    <ROW>
        <FLD1>P2</FLD1>
        <S_VAL>5</S_VAL>
        <FLD2>N3</FLD2>
    </ROW>
</ROWSET>
<ROW>
   <FLD1>P2</FLD1>
   <S_VAL>1</S_VAL>
   <FLD2>N2</FLD2>
</ROW>
<ROW>
   <FLD1>P3</FLD1>
   <S_VAL>3</S_VAL>
   <FLD2>N2</FLD2>
</ROW>