对来自两个不同路径的accNo字段进行排序

时间:2013-08-06 10:30:10

标签: xml xslt xslt-2.0

<?xml version="1.0" encoding="UTF-8"?>
<accountList>
    <previousAccount>
        <account>
            <name>NASH</name>
            <accountStatus>REMOVED</accountStatus>
            <accNo>1</accNo>
        </account>
        <account>
            <name>ADOGA</name>
            <accountStatus>REMOVED</accountStatus>
            <accNo>8</accNo>
        </account>
        <account>
            <name>LUCAS</name>
            <accountStatus>HOLD</accountStatus>
            <accNo>09</accNo>
        </account>
        <account>
            <name>DONALD</name>
            <accountStatus>HOLD</accountStatus>
            <accNo>21</accNo>
        </account>
        <account>
            <Title>Miss</Title>
            <firstName>HILARI</firstName>
            <lastName>WOOD</lastName>
            <city>LONDON</city>
            <accNo>24</accNo>
        </account>
    </previousAccount>
    <account>
        <Title>Mr</Title>
        <firstName>RICHARD</firstName>
        <lastName>JOHN</lastName>
        <city>london</city>
        <accNo>02</accNo>
    </account>
    <account>
        <Title>Mr</Title>
        <firstName>xxx</firstName>
        <lastName>JOHN</lastName>
        <city>London</city>
        <accNo>17</accNo>
    </account>
    <account>
        <Title>Mr</Title>
        <firstName>HEWIT</firstName>
        <lastName>JOHN</lastName>
        <city>LONDON</city>
        <accNo>20</accNo>
    </account>
    <account>
        <Title>Mr</Title>
        <firstName>xxx</firstName>
        <lastName>JOHN</lastName>
        <city>LONDON</city>
        <accNo>21</accNo>
    </account>
    <account>
        <Title>Mr</Title>
        <firstName>KEVIN</firstName>
        <lastName>PETE</lastName>
        <city>LONDON</city>
        <accNo>07</accNo>
    </account>
</accountList>
  

xslt代码

<xsl:stylesheet version="2.0"
        xsi:schemaLocation="http://www.w3.org/1999/XSL/Transform file:/C:/Users/n434947/Desktop/workspace/SonicXSLT/BA xslt page.xsd"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:fn="http://www.w3.org/2005/xpath-functions"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:output method="text"/>
    <xsl:variable name="newline">
 <xsl:text>
</xsl:text>
</xsl:variable>
    <xsl:template match="accountList">
        <xsl:for-each-group select="descendant::account" group-starting-with="*[firstName != 'xxx' or lastName != preceding-sibling::*[1]/lastName]">
            <xsl:sort select="accNo" order="ascending"/>
            <xsl:if test="previousAccount/account/accountStatus='REMOVED'">
            <xsl:value-of select="previousAccount/account[accountStatus='REMOVED']/accNo"/>
            </xsl:if>
            <xsl:value-of select="previousAccount/account[accountStatus='HOLD']/accNo"/>
            <xsl:value-of select="accNo"/>
            <xsl:text> </xsl:text>

            <xsl:value-of select="lastName"/>
            <xsl:text> </xsl:text>
            <xsl:value-of select="firstName"/>
            <xsl:value-of select="$newline"/>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

根据我的要求,我必须对两个不同的X路径(如下面的

)进行排序
accountList/previousAccount/account/accNo
accountList/account/accNo

我使用了后代,这对我的要求不起作用。请帮我解决这个问题。

实际输出

02 JOHN RICHARD
07 PETE KEVIN
1 
20 JOHN HEWIT
24 WOOD HILARI

期待输出

   01 REMOVED   NASH
   02           JOHN RICHARD
   07           PETE KEVIN
   08 REMOVED   ADOGA
   09 HOLD      LUCAS
   20           JOHN HEWIT
   24 HOLD       DONALD

1 个答案:

答案 0 :(得分:0)

  

在我的要求中,我得对它们进行排序,这些都来自两个   不同的X路径如下

accountList/previousAccount/account/accNo
accountList/account/accNo

也许你可以在没有两个不同XPath的地方做到这一点。如果你减少了上面的XPath,删除previousAccount就会发现它们基本相同。您只需要搜索accountList ...

的后代
accountList//account/accNo

如果您使用xsl:for-eachxsl:apply-templates执行此操作,您的排序会变得更加轻松。任何其他过滤,例如firstName != 'xxx'都可以添加到谓词中。

我认为这是你最初尝试的内容,但却因xsl:for-each-group而崩溃了。

这是一个例子(also seen here)。我完全猜测输出的实际格式;特别是田野的填充物。我可能过度复杂了,但它至少应该是一个开始。

XML输入

<accountList>
    <previousAccount>
        <account>
            <name>NASH</name>
            <accountStatus>REMOVED</accountStatus>
            <accNo>1</accNo>
        </account>
        <account>
            <name>ADOGA</name>
            <accountStatus>REMOVED</accountStatus>
            <accNo>8</accNo>
        </account>
        <account>
            <name>LUCAS</name>
            <accountStatus>HOLD</accountStatus>
            <accNo>09</accNo>
        </account>
        <account>
            <name>DONALD</name>
            <accountStatus>HOLD</accountStatus>
            <accNo>21</accNo>
        </account>
        <account>
            <Title>Miss</Title>
            <firstName>HILARI</firstName>
            <lastName>WOOD</lastName>
            <city>LONDON</city>
            <accNo>24</accNo>
        </account>
    </previousAccount>
    <account>
        <Title>Mr</Title>
        <firstName>RICHARD</firstName>
        <lastName>JOHN</lastName>
        <city>london</city>
        <accNo>02</accNo>
    </account>
    <account>
        <Title>Mr</Title>
        <firstName>xxx</firstName>
        <lastName>JOHN</lastName>
        <city>London</city>
        <accNo>17</accNo>
    </account>
    <account>
        <Title>Mr</Title>
        <firstName>HEWIT</firstName>
        <lastName>JOHN</lastName>
        <city>LONDON</city>
        <accNo>20</accNo>
    </account>
    <account>
        <Title>Mr</Title>
        <firstName>xxx</firstName>
        <lastName>JOHN</lastName>
        <city>LONDON</city>
        <accNo>21</accNo>
    </account>
    <account>
        <Title>Mr</Title>
        <firstName>KEVIN</firstName>
        <lastName>PETE</lastName>
        <city>LONDON</city>
        <accNo>07</accNo>
    </account>
</accountList>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:l="local" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  exclude-result-prefixes="#all">
  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:function name="l:pad">
    <xsl:param name="input" as="xs:string"/>
    <xsl:param name="length" as="xs:integer"/>
    <xsl:sequence select="l:pad($input,$length,'right')"/>
  </xsl:function>

  <xsl:function name="l:pad">
    <xsl:param name="input" as="xs:string"/>
    <xsl:param name="length" as="xs:integer"/>
    <xsl:param name="align" as="xs:string"/>
    <xsl:variable name="inputLength" select="string-length($input)"/>
    <xsl:variable name="padding" select="if ($length > $inputLength) then 
      for $x in 1 to ($length - $inputLength) return ' ' else ''"/>
    <xsl:sequence select="if ($align = 'right') then 
      string-join(($padding,$input),'') else
      string-join(($input,$padding),'')"/>
  </xsl:function>

  <xsl:template match="/*">
    <xsl:for-each select=".//account[not(firstName = 'xxx')]">
      <xsl:sort select="accNo" data-type="number"/>
      <xsl:if test="not(position()=1)"><xsl:text>&#xA;</xsl:text></xsl:if>
      <xsl:value-of select="l:pad(
        l:pad(format-number(accNo,'00'),5),6,'left')"/>
      <xsl:value-of select="l:pad(
        concat(accountStatus,' '),10,'left')"/>
      <xsl:value-of select="l:pad(
        string-join((lastName,name|firstName),' '),20,'left')"/>      
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

输出(这对我来说并不明显为什么&#34; WOOD HILARI&#34;应该被排除在外)

   01 REMOVED   NASH                
   02           JOHN RICHARD        
   07           PETE KEVIN          
   08 REMOVED   ADOGA               
   09 HOLD      LUCAS               
   20           JOHN HEWIT          
   21 HOLD      DONALD              
   24           WOOD HILARI