How to jump out of the loop and access previous elements - xpath

have one XML Structure:
<INFO>
<para Type="07">07 L„hetysluettelo</para>
<para Type="+0">+0 074064</para>
<para Type="07">07 Tilausnumero Ostajan viite</para>
<para Type="+0">+0 044275 5549177</para>
<para Type=" 0"> 0 836679586 (LONG 2478 3.63 8995.14</para>
<para Type="07">07 L„hetysluettelo2</para>
<para Type="+0">+0 074517</para>
<para Type="07">07 Tilausnumero Ostajan viite</para>
<para Type="+0">+0 044276 5534435</para>
<para Type=" 0"> 0 836679586 (LONG 2478 3.63 8995.14</para>
<para Type=" 0"> 0 L1 KUORMAL. 800 14 0.00 0.00</para>
</INFO>
I would like to use loop on para which has type SPACE0. By doing this i would alos like to fetch its previous data elements for example: +0 and 07 segments.
I am looking for this output:
<ROWS>
<ROW>
<NUMBER>074064</NUMBER>
<ORDER_NUMBER>044275</ORDER_NUMBER>
<REF>5549177</REF>
<NAME>836679586 (LONG</NAME>
<COUNT>2478</COUNT>
<PRICE>3.63</PRICE>
<TOTAL>8995.14</TOTAL>
</ROW>
<ROW>
<NUMBER>074517</NUMBER>
<ORDER_NUMBER>044276</ORDER_NUMBER>
<REF>5534435</REF>
<NAME>836679586 (LONG</NAME>
<COUNT>2478</COUNT>
<PRICE>3.63</PRICE>
<TOTAL>8995.14</TOTAL>
</ROW>
<ROW>
<NUMBER>074517</NUMBER>
<ORDER_NUMBER>044276</ORDER_NUMBER>
<REF>5534435</REF>
<NAME>L1 KUORMAL. 800</NAME>
<COUNT>14</COUNT>
<PRICE>0.00</PRICE>
<TOTAL>0.00</TOTAL>
</ROW>
</ROWS>
in some cases the elements NUMBER, ORDER_NUMBER, and REF value will remain the same because they belong to same segment.
Is it possible to do this?
I have tried this:
<xsl:for-each select="INFO/para[#Type=' 0']">
<ROW>
<NUMBER>
<xsl:value-of select="normalize-space(substring(../following-sibling::para[1],6,24))"/>
</NUMBER>
<ORDER_NUMBER>
<xsl:value-of select="normalize-space(substring(../following-sibling::para[3],7,24))"/>
</ORDER_NUMBER>
<REF>
<xsl:value-of select="normalize-space(substring(../following-sibling::para[3],31,50))"/>
</REF>
<NAME>
<xsl:value-of select="normalize-space(substring(.,7,24))"/>
</NAME>
<COUNT>
<xsl:value-of select="normalize-space(substring(.,33,8))"/>
</COUNT>
<PRICE>
<xsl:value-of select="normalize-space(substring(.,41,11))"/>
</PRICE>
<TOTAL>
<xsl:value-of select="normalize-space(substring(.,69,11))"/>
</TOTAL>
</ROW>
</xsl:for-each>
Thanks.

By using substring functions and nested loops, it worked well. So marking it closed.

Related

How to sort the 'joined' xsl nodeset

I have this (simplified) XML
<?xml version="1.0" encoding="iso-8859-1"?>
<LENEX version="3.0">
<MEETS>
<MEET name="British Gas Champs 2012">
<SESSIONS>
<SESSION number="1" name="Session 1" course="LCM" date="2012-07-22">
<EVENTS>
<EVENT eventid="104" number="104" gender="M" round="PRE" order="4">
<SWIMSTYLE distance="100" stroke="BACK" name="Boys 14 Yrs 100m Backstroke" />
<AGEGROUPS>
<AGEGROUP agegroupid="1" name="14 Yrs Age Group">
<RANKINGS>
<RANKING place="3" resultid="1" />
</RANKINGS>
</AGEGROUP>
</AGEGROUPS>
</EVENT>
</EVENTS>
</SESSION>
<SESSION number="2" name="Session 2" course="LCM" date="2012-07-22">
<EVENTS>
<EVENT eventid="207" number="207" gender="M" round="PRE" order="7">
<SWIMSTYLE distance="100" stroke="FREE" name="Boys 14 Yrs 100m Freestyle"/>
<AGEGROUPS>
<AGEGROUP agegroupid="1" name="14 Yrs Age Group">
<RANKINGS>
<RANKING place="1" resultid="2"/>
</RANKINGS>
</AGEGROUP>
</AGEGROUPS>
</EVENT>
</EVENTS>
</SESSION>
</SESSIONS>
<CLUBS>
<CLUB name="Aberdeen ASC" region="X" type="CLUB">
<ATHLETES>
<ATHLETE athleteid="1169" lastname="Butt" firstname="Suleman">
<RESULTS>
<RESULT resultid="1" eventid="104" swimtime="00:01:01.18"/>
<RESULT resultid="2" eventid="207" swimtime="00:00:53.06"/>
</RESULTS>
</ATHLETE>
</ATHLETES>
</CLUB>
</CLUBS>
</MEET>
</MEETS>
</LENEX>
and this stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl">
<xsl:variable name="session" select="/LENEX/MEETS/MEET/SESSIONS/SESSION" />
<xsl:variable name="athlete" select="/LENEX/MEETS/MEET/CLUBS/CLUB/ATHLETES/ATHLETE" />
<!-- variable for testing/debugging-->
<xsl:variable name="athlno" select="1169" />
<!--<xsl:param name="evno" />-->
<xsl:template match="/">
<html>
<head>
</head>
<body>
<xsl:apply-templates select="$athlete" />
</body>
</html>
</xsl:template>
<!-- find the results (#resultid) for athleteid in $athlno -->
<xsl:template match="ATHLETE[#athleteid]">
<xsl:choose>
<xsl:when test="self::ATHLETE[#athleteid = $athlno]/RESULTS">
<xsl:apply-templates select="child::RESULTS/RESULT">
<!-- these 'sorts' works -->
<!-- <xsl:sort select="#resultid" data-type="text" order="descending"/>
<xsl:sort select="#eventid" order="descending"/> -->
</xsl:apply-templates>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- create $res1 $stim1 variables to pass to 'SESSIONS' node -->
<xsl:template match="RESULT">
<xsl:variable name="res1" ><xsl:value-of select="#resultid"/></xsl:variable>
<xsl:variable name="stim1" ><xsl:value-of select="#swimtime"/></xsl:variable>
<tr>
<!--join to 'SESSIONS' node -->
<xsl:apply-templates select="$session/EVENTS/EVENT">
<!-- this xsl:sort doesn't work
<xsl:sort select="#number" data-type="text" order="descending"/>-->
<xsl:with-param name="res2" select="$res1"/>
<xsl:with-param name="stim2" select="$stim1"/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="EVENT">
<xsl:param name="res2" />
<xsl:param name="stim2" />
<xsl:for-each select="child::AGEGROUPS/AGEGROUP/RANKINGS/RANKING[#resultid = $res2]">
<!-- this xsl:sort doesn't work -->
<xsl:sort select="#place" data-type="text" order="ascending"/>
<xsl:value-of select="#place"/>
<xsl:choose>
<xsl:when test="../../../../#round = 'TIM'">
<xsl:text> </xsl:text>HDW
</xsl:when>
<xsl:when test="../../../../#round = 'PRE'">
<xsl:text> </xsl:text>Heat
</xsl:when>
<xsl:when test="../../../../#round = 'SEM'">
<xsl:text> </xsl:text>Semi-F
</xsl:when>
<xsl:when test="../../../../#round = 'FIN'">
<xsl:text> </xsl:text>Final
</xsl:when>
<xsl:otherwise>
<xsl:text> </xsl:text>n/a
</xsl:otherwise>
</xsl:choose>
<xsl:text> </xsl:text><xsl:value-of select="../../../../SWIMSTYLE/#name" />
<xsl:text> </xsl:text><xsl:value-of select="substring($stim2,4)"/>
<xsl:text> </xsl:text><xsl:value-of select="../../../../#number" /><br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I only seem to be able to sort by the main nodeset ie RESULTS/RESULT/#resultid or RESULTS/RESULT/eventid. I would like to sort the results of a 'join' by EVENT/SWIMSTYLE/#stroke, EVENT/SWIMSTYLE/#distance and EVENT/#round. I am limited to XSLT 1.0. What I've tried is commented in the XSLT above.
The output I'm looking for is ...
3 Final Boys 14 Yrs 100m Backstroke 01:00.83 269
3 Heat Boys 14 Yrs 100m Backstroke 01:01.18 104
3 Semi-F Boys 14 Yrs 100m Backstroke 01:00.66 156
1 Final Boys 14 Yrs 100m Freestyle 00:52.61 363
1 Heat Boys 14 Yrs 100m Freestyle 00:53.06 207
1 Semi-F Boys 14 Yrs 100m Freestyle 00:53.56 259
1 Final Boys 14 Yrs 200m Freestyle 01:53.34 555
1 Heat Boys 14 Yrs 200m Freestyle 01:57.29 402
1 Semi-F Boys 14 Yrs 200m Freestyle 01:55.23 454
1 Final Boys 14 Yrs 400m Freestyle 04:03.46 351
1 Heat Boys 11/14 Yrs 400m Freestyle 04:09.46 301
A few keys will help you build paths to your sort attributes:
<!-- Map from #resultid to EVENT -->
<xsl:key name="result-event" match="//EVENT" use="descendant::RANKING/#resultid"/>
<!-- Map from #resultid to RANKING -->
<xsl:key name="ranking" match="//RANKING" use="#resultid"/>
Then, when templating the RESULT elements for an ATHLETE, you can reference the sort attributes:
<xsl:template match="/">
<xsl:apply-templates select="//ATHLETE"/>
</xsl:template>
<xsl:template match="ATHLETE">
<xsl:apply-templates select="RESULTS/RESULT">
<xsl:sort select="key('result-event', #resultid)/SWIMSTYLE/#stroke"/>
<xsl:sort select="key('result-event', #resultid)/SWIMSTYLE/#distance" data-type="number"/>
<xsl:sort select="key('result-event', #resultid)/#round"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="RESULT">
<xsl:value-of select="key('ranking', #resultid)/#place"/>
<xsl:apply-templates select="key('result-event', #resultid)"/>
<xsl:value-of select="#swimtime"/>
<br/>
</xsl:template>
<xsl:template match="EVENT">
<xsl:text> </xsl:text><xsl:value-of select="#round"/>
<xsl:text> </xsl:text><xsl:value-of select="SWIMSTYLE/#name" />
<xsl:text> </xsl:text><xsl:value-of select="../../#number" />
</xsl:template>
You can adjust the sort order for rounds by using a lookup table to map the #round key to an arbitrary surrogate key.

Grouping in XSLT 2.0 (grouping by text)

I have a problem figuring out this grouping in xslt:
The initial information:
<Application>
<ApplicationItem LayoutPath="Attachments.Package.Attachment[bfd0b74d-2888-49d9-a986-df807f08ad8a].UniqueID" Value="bfd0b74d-2888-49d9-a986-df807f08ad8a" />
<ApplicationItem LayoutPath="Attachments.Package.Attachment[bfd0b74d-2888-49d9-a986-df807f08ad8a].Filename" Value="Document 1 Test" />
<ApplicationItem LayoutPath="Attachments.Package.Attachment[bfd0b74d-2888-49d9-a986-df807f08ad8a].URI" Value="https/.test.pdf" />
<ApplicationItem LayoutPath="Attachments.Package.Attachment[bfd0b74d-2888-49d9-a986-df807f08ad8b].UniqueID" Value="bfd0b74d-2888-49d9-a986-df807f08ad8b" />
<ApplicationItem LayoutPath="Attachments.Package.Attachment[bfd0b74d-2888-49d9-a986-df807f08ad8b].Filename" Value="Document 2 Test" />
<ApplicationItem LayoutPath="Attachments.Package.Attachment[bfd0b74d-2888-49d9-a986-df807f08ad8b].URI" Value="google.com" />
</Application>
The expected result:
<Package>
<Attachment UniqueID="bfd0b74d-2888-49d9-a986-df807f08ad8a"
Filename="Document 1 Test"
URI="https/.test.pdf"/>
<Attachment UniqueID="bfd0b74d-2888-49d9-a986-df807f08ad8b"
Filename="Document 2 Test"
URI="google.com"/>
<Package>
My code:
I've done the grouping by using the id from the square brackets.
<xsl:for-each-group select="ApplicationItem[contains(#LayoutPath,'Attachments.Package.Attachment')]" group-by="substring-before(substring-after(#LayoutPath, 'Attachments.Package.Attachment['), ']')">
<Attachment>
<xsl:for-each select="current-group()">
<xsl:attribute name="UniqueID" select="current-grouping-key()"/>
<xsl:attribute name="Filename" select=".[contains(#LayoutPath,'Filename')]/#Value"/>
<xsl:attribute name="URI" select=".[contains(#LayoutPath,'URI')]/#Value"/>
</xsl:for-each>
<Attachment>
</xsl:for-each-group>
My results:
<Package>
<Attachment UniqueID="bfd0b74d-2888-49d9-a986-df807f08ad8a"
Filename=""
URI="https/.test.pdf"/>
<Attachment UniqueID="bfd0b74d-2888-49d9-a986-df807f08ad8b"
Filename=""
URI="google.com"/>
<Package>
What i need to change in code to use the grouping because for now is not working taking only the last ApplicationItem with the unique #LayoutPath.
I think the problem is with the grouping but don't now how to fix it.
Remove the <xsl:for-each select="current-group()"> and change
<xsl:attribute name="Filename" select=".[contains(#LayoutPath,'Filename')]/#Value"/>
<xsl:attribute name="URI" select=".[contains(#LayoutPath,'URI')]/#Value"/>
to
<xsl:attribute name="Filename" select="current-group()[contains(#LayoutPath,'Filename')]/#Value"/>
<xsl:attribute name="URI" select="current-group()[contains(#LayoutPath,'URI')]/#Value"/>

how to express xpath 1.0 count function?

I have a document like the one below and I need the count of each subitem[#role="special"] starting from its parent item.
My problem is that I need to calculate the number for the subitem and the same value for any nested subitems in that subitem. So for all subitems that are descendants of subitem[#role="special"] I should always get the same value. I've labeled what I want in the tree below with (want N)
<root>
<item role="special">
<name>One</name>
<subitem>
<name>A (want 0)</name>
</subitem>
</item>
<item>
<name>Two</name>
<subitem role="special">
<name>B (want 1)</name>
<subitem>
<name>B b (want 1)</name>
</subitem>
</subitem>
<subitem>
<name> C (want 0)</name>
<subitem>C c (want 0)</subitem>
</subitem>
<subitem role="special">
<name> D (want 2)</name>
<subitem>
<name>D d (want 2)</name>
</subitem>
</subitem>
</item>
</root>
These are the kinds of things I've tried but I'm beginning to wonder if what I want is possible:
<xsl:template match="subitem">
<xsl:value-of select="count(ancestor-or-self::subitem[#role='special'])"/>
<xsl:value-of select="count(preceding-sibling::subitem[#role='special'])"/>
<xsl:text>
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
that itself returns:
00
10
10
01
00
11
10
Is there a way to accomplish this?
If I understood correctly, you have three cases: the current subitem is special itself or is descendant of a special item or is not special. Then we can use a choose condition for it and treat each case as applicable:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="subitem">
<xsl:choose>
<xsl:when test="#role='special'">
<xsl:value-of select="count(preceding-sibling::subitem[#role='special'])+1" />
</xsl:when>
<xsl:when test="ancestor::subitem[#role='special']">
<xsl:value-of select="count(preceding::subitem[#role='special'])+1" />
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
<xsl:text>
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>

XPath to parse eCFR XML using attributes and nodes

This question has been significantly edited to make things a bit clearer.
I am attempting to pull data out of the electronic Code of Federal Regulations XML feed (http://www.gpo.gov/fdsys/bulkdata/CFR/2015/title-15/CFR-2015-title15-vol2.xml) and am having trouble.
Specifically, I'd like to grab data that will be matched by a combination of Node and Attribute. In the following snippet of XML, you can see some of the text I'd like to grab. I would like to obtain the data for each FP node where the attribute FP-2 is present. I would also like to grab the data for each FP node having the attribute FP-1.
<APPENDIX>
<EAR>Pt. 774, Supp. 1</EAR>
<HD SOURCE="HED">Supplement No. 1 to Part 774—The Commerce Control List</HD>
<HD SOURCE="HD1">Category 0—Nuclear Materials, Facilities, and Equipment [and Miscellaneous Items]</HD>
<HD SOURCE="HD1">A. “End Items,” “Equipment,” “Accessories,” “Attachments,” “Parts,” “Components,” and “Systems”</HD>
<FP SOURCE="FP-2">
<E T="02">0A002Power generating or propulsion equipment “specially designed” for use with space, marine or mobile “nuclear reactors”. (These items are “subject to the ITAR.” See 22 CFR parts 120 through 130.)</E>
</FP>
<FP SOURCE="FP-2">
<E T="02">0A018Items on the Wassenaar Munitions List (see List of Items Controlled).</E>
</FP>
<FP SOURCE="FP-1">
<E T="04">License Requirements</E>
</FP>
<FP SOURCE="FP-1">
<E T="03">Reason for Control:</E> NS, AT, UN</FP>
<GPOTABLE CDEF="s50,r50" COLS="2" OPTS="L2">
<BOXHD>
<CHED H="1">Control(s)</CHED>
<CHED H="1">Country Chart (See Supp. No. 1 to part 738)</CHED>
</BOXHD>
<ROW>
<ENT I="01">NS applies to entire entry</ENT>
<ENT>NS Column 1.</ENT>
</ROW>
<ROW>
<ENT I="01">AT applies to entire entry</ENT>
<ENT>AT Column 1.</ENT>
</ROW>
<ROW>
<ENT I="01">UN applies to entire entry</ENT>
<ENT>See § 746.1(b) for UN controls.</ENT>
</ROW>
</GPOTABLE>
<FP SOURCE="FP-1">
<E T="05">List Based License Exceptions (See Part 740 for a description of all license exceptions)</E>
</FP>
<FP SOURCE="FP-1">
<E T="03">LVS:</E> $3,000 for 0A018.b</FP>
<FP SOURCE="FP-1">$1,500 for 0A018.c and .d</FP>
<FP SOURCE="FP-1">
<E T="03">GBS:</E> N/A</FP>
<FP SOURCE="FP-1">
<E T="03">CIV:</E> N/A</FP>
<FP SOURCE="FP-1">
<E T="04">List of Items Controlled</E>
</FP>
<FP SOURCE="FP-1">
<E T="03">Related Controls:</E> (1) See also 0A979, 0A988, and 22 CFR 121.1 Categories I(a), III(b-d), and X(a). (2) See ECCN 0A617.y.1 and .y.2 for items formerly controlled by ECCN 0A018.a. (3) See ECCN 1A613.c for military helmets providing less than NIJ Type IV protection and ECCN 1A613.y.1 for conventional military steel helmets that, immediately prior to July 1, 2014, were classified under 0A018.d and 0A988. (4) See 22 CFR 121.1 Category X(a)(5) and (a)(6) for controls on other military helmets.</FP>
<FP SOURCE="FP-1">
<E T="03">Related Definitions:</E> N/A</FP>
<FP>
<E T="03">Items:</E> a. [Reserved]</FP>
<P>b. “Specially designed” components and parts for ammunition, except cartridge cases, powder bags, bullets, jackets, cores, shells, projectiles, boosters, fuses and components, primers, and other detonating devices and ammunition belting and linking machines (all of which are “subject to the ITAR.” (See 22 CFR parts 120 through 130);</P>
<NOTE>
<HD SOURCE="HED">
<E T="03">Note:</E>
</HD>
<P>
<E T="03">0A018.b does not apply to “components” “specially designed” for blank or dummy ammunition as follows:</E>
</P>
<P>
<E T="03">a. Ammunition crimped without a projectile (blank star);</E>
</P>
</APPENDIX>
To complicate matters, I'm trying to pull this data into Filemaker, but upon edit, I'll stick to simple XSL.
The following XSL grabs all of the FP nodes without differentiation.
<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="//FP">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Modifying this to match on xsl:template match="FP[#SOURCE='FP-1'] allows me to make the necessary match based on the attribute, but I'm still not clear on how to capture the data I need. Thoughts?
A few things:
Your XSLT actually is not an XSLT format
In XPath, to reference an attribute (i.e., SOURCE), it must be prefixed with #.
Finally, there are many FP1s and FP2s but your setup only choose first instances.
Consider the following XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8"/>
<xsl:template match="/">
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<METADATA>
<FIELD NAME="ECCNFP_2" TYPE="TEXT"/>
<FIELD NAME="ECCNFP_1" TYPE="TEXT"/>
</METADATA>
<RESULTSET>
<xsl:for-each select="//FP[#SOURCE = 'FP-2']/E[#T='02']">
<ROW>
<COL>
<DATA><xsl:value-of select="substring(.,1,5)"/></DATA>
</COL>
</ROW>
</xsl:for-each>
<xsl:for-each select="//FP[#SOURCE = 'FP-1']/E[#T='02']">
<ROW>
<COL>
<DATA><xsl:value-of select="substring(.,1,5)"/></DATA>
</COL>
</ROW>
</xsl:for-each>
</RESULTSET>
</FMPXMLRESULT>
</xsl:template>
</xsl:stylesheet>
Which would output:
<?xml version='1.0' encoding='UTF-8'?>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<METADATA>
<FIELD NAME="ECCNFP_2" TYPE="TEXT"/>
<FIELD NAME="ECCNFP_1" TYPE="TEXT"/>
</METADATA>
<RESULTSET>
<ROW>
<COL>
<DATA>0A002</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>0A018</DATA>
</COL>
</ROW>
</RESULTSET>
</FMPXMLRESULT>
And partial output of full web link xml:
<?xml version='1.0' encoding='UTF-8'?>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<METADATA>
<FIELD NAME="ECCNFP_2" TYPE="TEXT"/>
<FIELD NAME="ECCNFP_1" TYPE="TEXT"/>
</METADATA>
<RESULTSET>
<ROW>
<COL>
<DATA>2A000</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>0A002</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>0A018</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>0A521</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>0A604</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>0A606</DATA>
</COL>
</ROW>
...
In fact, point your XSLT processor to the GPO link and all FP1s and FP2s output. I just did so with Python! Close to 3,000 lines!
Your question is still not clear. If I concentrate on this part:
I would like to obtain the data for each FP node where the attribute
FP-2 is present. I would also like to grab the data for each FP node
having the attribute FP-1.
then you probably want to change this:
<xsl:for-each select="//FP">
to:
<xsl:for-each select="//FP[#SOURCE='FP-1' or #SOURCE='FP-2']">
Note that this returns the value of each FP element where the SOURCE attribute has a value of either 'FP-1' or 'FP-2'. I see no "FP node where the attribute FP-2 is present" in your input.
Note also that the // syntax is expensive in terms of processing power. You will get better performance if you use a full, explicit path.

sort in xslt when before creating table of data

I am trying to take the data and put in a table and sort it before I output to the table and when I do it sorts the first columun and rest of the column are not sorted at all. I am trying to sort by streetNuame and only works on the first table column
<fo:table>
<fo:table-column width="82mm"/>
<fo:table-column width="82mm"/>
<fo:table-column width="82mm"/>
<fo:table-body>
<xsl:for-each select="route/address[position() mod 3 = 1]">
<xsl:sort select="streetName"/>
<fo:table-row>
<xsl:apply-templates select=". | following-sibling::*[3 > position()]"/>
<xsl:variable name="vPos" select="position()"/>
<xsl:variable name="vUnfilled"
select=" 2 - count(following-sibling::*)"/>
<xsl:if test="position() = last()">
<xsl:for-each select="../*[not(position() > $vUnfilled)]">
<fo:table-cell>
<fo:block>
<xsl:value-of select="' '"/>
</fo:block>
</fo:table-cell>
</xsl:for-each>
</xsl:if>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
XML below:
<route>
<name>blah</name>
<address>
<fullStreet>blah</fullStreet>
<streetNumber>blah</streetNumber>
<streetName>blah</streetName>
</address>

Resources