1
<?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 路径的 accNo 进行排序,如下所示

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
4

1 回答 1

0

In my requirement ,I got to sort accNo which are all from two different X paths like below

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

Maybe you can do it where you don't have two different XPaths. If you reduce your XPaths above, by removing previousAccount you see that they basically the same. You just need to search descendants of accountList...

accountList//account/accNo

If you do this with an xsl:for-each or an xsl:apply-templates your sorting becomes easier. Any additional filtering, like firstName != 'xxx' can be added to the predicate.

I think this is what you were originally trying, but it fell apart with xsl:for-each-group.

Here's an example (also seen here). I'm completely guessing at the actual format of the output; especially the padding of the fields. I probably over complicated it a bit, but it should be a start at least.

XML Input

<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>

Output (it wasn't obvious to me why "WOOD HILARI" was supposed to be excluded)

   01 REMOVED   NASH                
   02           JOHN RICHARD        
   07           PETE KEVIN          
   08 REMOVED   ADOGA               
   09 HOLD      LUCAS               
   20           JOHN HEWIT          
   21 HOLD      DONALD              
   24           WOOD HILARI         
于 2017-03-16T21:57:34.830 回答