Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old June 14th, 2007, 12:10 AM
Registered User
 
Join Date: Jun 2007
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default Selecting multiple elements from the source XML

Hi,

I am new to XSLT. I am trying to select multiple PersDriver elements from the source XML using XSLT. Here is how my XSLT looks like:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
      <xsl:template match="/ACORD">
            <policy>
            <pos_policy>
            â€¦â€¦â€¦â€¦â€¦â€¦â€¦â€¦
            </pos_policy>
               <drivers>
                  <xsl:for-each select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness[PersDriver/@id]">
                  <driver>
                  <driver_number>
                        <xsl:value-of select="substring-after(/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/@id, 'PersDriver')"/>
                  </driver_number>
                  <first_name>
                        <xsl:value-of select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/GeneralPartyInfo/NameInfo/PersonName/GivenName"/>
                  </first_name>
                  <last_name>
                        <xsl:value-of select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/GeneralPartyInfo/NameInfo/PersonName/Surname"/>
                  </last_name>
                  </driver>
                  </xsl:for-each>
             </drivers>
            </policy>
            </xsl:template>
<xsl:template match="PersDriver">
                <xsl:value-of select="."/>
            </xsl:template>
</xsl:stylesheet>

Where my source XML has three driver elements:
<PersDriver id=”PersDriver1”>
........
</PersDriver>
<PersDriver id=”PersDriver2”>
........
</PersDriver>
<PersDriver id=”PersDriver3”>
........
</PersDriver>

However, no matter what I do, it selects only driver1. Driver 2 and 3 are never selected into the output.
I also tried this syntax:
<drivers>
                        <xsl:for-each select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness[PersDriver/@id='PersDriver2']">
                                    <xsl:call-template name="OutputDriver"/>
                        </xsl:for-each>
  </drivers>
<xsl:template name="OutputDriver">
<driver>
      <driver_number>
            <xsl:value-of select="substring-after(/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/@id, 'PersDriver')"/>
      </driver_number>
………………………….
</driver>
It always picks the driver# 1.

Then I tried the following:
            <drivers>

                <xsl:for-each select="range[@id_range=('1','2','3','4')]">
                  <xsl:variable name="driverId">
                        <xsl:value-of select="substring-after(/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/@id, 'PersDriver')"/>
                </xsl:variable>
                <xsl:for-each select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver">
          <xsl:choose>
        <xsl:when test="$driverId='1'">

    <xsl:element name="driver_number">
    <xsl:value-of select="substring-after(/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/@id, 'PersDriver')"/>
    </xsl:element> </xsl:when>
    <xsl:when test="$driverId='2'">
    <xsl:element name="driver_number">
        <xsl:value-of select="substring-after(/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/@id, 'PersDriver')"/>
    </xsl:element> </xsl:when>
        </xsl:choose>
    </xsl:for-each>
    </xsl:for-each>
</drivers>

and I got the following error:
javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: Expected ), but found: ,

I am also not sure if the above syntax will select all the driver elements?

Any help will be greatly appreciated! Thanks in advance!!

Best regards,
mkansal


 
Old June 14th, 2007, 02:52 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You're doing:

<xsl:for-each select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness[PersDriver/@id]">
 ...
                        <xsl:value-of select="substring-after(/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/@id, 'PersDriver')"/>

within a for-each, you usually want to select relative to the current node being processed by the for-each, whereas you're selecting from the top of the document (that's what the leading "/" means). Change it to

<xsl:value-of select="substring-after(PersDriver/@id, 'PersDriver')"/>

A 2.0 processor here would give you an error, because the argument to substring-after has to be a single string. But a 1.0 processor simply takes the first node selected, and ignores the rest.


This syntax:

range[@id_range=('1','2','3','4')]

is valid in XPath 2.0 but not in 1.0, and I think this accounts for the error message - so you appear to be using a 1.0 processor.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 14th, 2007, 10:40 AM
Registered User
 
Join Date: Jun 2007
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hello Mr. Kay,

Thanks a lot for your response! I tried the following, as you suggested:

<drivers>
<xsl:for-each select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness[PersDriver/@id]">
    <driver>
             <driver_number>
                <xsl:value-of select="substring-after(PersDriver/@id, 'PersDriver')"/>
              </driver_number>
        </driver>
</xsl:for-each>
</drivers>

</xsl:template>
     <xsl:template match="PersDriver">
     <xsl:value-of select="."/>
</xsl:template>

It's working fine for the first driver. However, the problem is that it's selecting only the 1st driver. It's not selcting the other two drivers from the source XML, even though I am using 'for-each'. Could you please tell what do I need to do extra to make this work?

Thanks much!

Best Regards,
mkansal

 
Old June 14th, 2007, 10:56 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Perhaps PersAutoLineBusiness only has one PersDriver child? You haven't actually shown us your source data.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 14th, 2007, 12:00 PM
Registered User
 
Join Date: Jun 2007
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hello Mr. Kay,

My source XML file is very big. However, here are some of the data elements showing the 3 'PersDriver' driver elements:
- <ACORD>
+ <SignonRq>
- <SignonPswd>
- <PersAutoLineBusiness>
- <PersDriver id="PersDriver1">
- <GeneralPartyInfo>
+ <NameInfo>
- <PersonName>
  </PersonName>
  </NameInfo>
+ <Addr>
  <AddrTypeCd>StreetAddress</AddrTypeCd>
  <Addr1>223 summer</Addr1>
  <Addr2>apt #1</Addr2>
  <City>Seattle</City>
  <StateProvCd>WA</StateProvCd>
  <PostalCode>98104</PostalCode>
  <County>KING</County>
  </Addr>
- <Communications>
- <PhoneInfo>
  <CommunicationUseCd>Home</CommunicationUseCd>
  <PhoneNumber>+1-555-5555555+123</PhoneNumber>
  </PhoneInfo>
  </Communications>
  </GeneralPartyInfo>
+ <DriverInfo>
- <PersonInfo>
  <GenderCd></GenderCd>
  <BirthDt></BirthDt>
  <MaritalStatusCd></MaritalStatusCd>
  </PersonInfo>
- <DriversLicense>
  <LicensedDt>1986-10-11</LicensedDt>
  <DriversLicenseNumber>akdfisd85226</DriversLicenseNumber>
  <FirstLicensedCurrentStateDt>1986-10-11</FirstLicensedCurrentStateDt>
  <StateProvCd>WA</StateProvCd>
  <CountryCd>US</CountryCd>
  </DriversLicense>
  </DriverInfo>
+ <PersDriverInfo VehPrincipallyDrivenRef="PersVeh1">
  <DefensiveDriverDt>2007-05-11</DefensiveDriverDt>
  <DefensiveDriverCd>N</DefensiveDriverCd>
  <DistantStudentInd>0</DistantStudentInd>
    </PersDriverInfo>
  </PersDriver>
- <PersDriver id="PersDriver2">
- <GeneralPartyInfo>
- <NameInfo>
- <PersonName>
  </PersonName>
  </NameInfo>
  </GeneralPartyInfo>
+ <DriverInfo>
- <PersonInfo>
  <GenderCd></GenderCd>
  <BirthDt></BirthDt>
  <MaritalStatusCd></MaritalStatusCd>
  <OccupationClassCd></OccupationClassCd>
  </PersonInfo>
- <DriversLicense>
  <LicensedDt>1991-05-01</LicensedDt>
  <DriversLicenseNumber>akdfisd85253</DriversLicenseNumber>
  <FirstLicensedCurrentStateDt>1991-05-01</FirstLicensedCurrentStateDt>
  <StateProvCd>WA</StateProvCd>
  <CountryCd>US</CountryCd>
  </DriversLicense>
  </DriverInfo>
+ <PersDriverInfo VehPrincipallyDrivenRef="PersVeh2">
  <DefensiveDriverDt>2007-05-11</DefensiveDriverDt>
  <DefensiveDriverCd>Y</DefensiveDriverCd>
  <DistantStudentInd>0</DistantStudentInd>
  </PersDriverInfo>
  </PersDriver>
- <PersDriver id="PersDriver3">
- <GeneralPartyInfo>
- <NameInfo>
+ <PersonName>
  </PersonName>
  </NameInfo>
  </GeneralPartyInfo>
+ <DriverInfo>
- <PersonInfo>
  <GenderCd></GenderCd>
  <BirthDt></BirthDt>
  <MaritalStatusCd></MaritalStatusCd>
  <OccupationClassCd></OccupationClassCd>
  </PersonInfo>
- <DriversLicense>
  <LicensedDt>1999-04-11</LicensedDt>
  <DriversLicenseNumber>akdfisd85251</DriversLicenseNumber>
  <FirstLicensedCurrentStateDt>1999-04-11</FirstLicensedCurrentStateDt>
  <StateProvCd>WA</StateProvCd>
  <CountryCd>US</CountryCd>
  </DriversLicense>
  </DriverInfo>
  </PersDriverInfo>
  </PersDriver>
- <PersVeh id="PersVeh1" RatedDriverRef="PersDriver1" LocationRef="Location1">
  <Manufacturer>MAZDA</Manufacturer>
  <Model>B2300 BASE/B2300 4 PK</Model>
  <ModelYear>2005</ModelYear>
  <VehBodyTypeCd>PU</VehBodyTypeCd>
.................
</ACORD>

Thanks!

Best regards,
mkansal

 
Old June 14th, 2007, 12:09 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I don't really know what this +/- notation is supposed to mean, but your path expression contains InsuranceSvcRq/PersAutoPolicyQuoteInqRq and I don't see either of those elements in your source, so I'm surprised it selects anything at all.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 14th, 2007, 12:30 PM
Registered User
 
Join Date: Jun 2007
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Sorry, here it is again. The '+' sign means, the element is expandable and has children. I opened the XML in browser and collapsed some elements to make the source XML shorter. That's why you are seeing those '+' and '-' signs.

- <ACORD>
+ <SignonRq>
- <SignonPswd>
- <InsuranceSvcRq>
  <RqUID>8D6B1F3F-0C55-4018-A6DF-6B0030ED6DEE</RqUID>
  <SPName></SPName>
- <PersAutoPolicyQuoteInqRq>
  <RqUID>8D6B1F3F-0C55-4018-A6DF-6B0030ED6DEE</RqUID>
  <TransactionRequestDt>2007-05-11T12:58:041-06:00</TransactionRequestDt>
  <TransactionEffectiveDt>2008-04-13</TransactionEffectiveDt>
  <CurCd></CurCd>
+ <Producer>
- <GeneralPartyInfo>
- <NameInfo>
- <CommlName>
  <CommercialName></CommercialName>
  </CommlName>
  </NameInfo>
- <Addr>
  <Addr1>1223</Addr1>
  <Addr2>456 test</Addr2>
  <StateProvCd>WA</StateProvCd>
  <PostalCode />
  </Addr>
  </GeneralPartyInfo>
- <ProducerInfo>
  <ContractNumber>testu</ContractNumber>
  </ProducerInfo>
  </Producer>
+ <InsuredOrPrincipal>
- <GeneralPartyInfo>
- <NameInfo>
  </GeneralPartyInfo>
- <InsuredOrPrincipalInfo>
  <InsuredOrPrincipalRoleCd>Insured</InsuredOrPrincipalRoleCd>
- <PersonInfo>
  <GenderCd></GenderCd>
  <BirthDt></BirthDt>
  <MaritalStatusCd></MaritalStatusCd>
  </PersonInfo>
  </InsuredOrPrincipalInfo>
  </InsuredOrPrincipal>
+ <PersPolicy>
...........
  </PersPolicy>
- <PersAutoLineBusiness>
- <PersDriver id="PersDriver1">
- <GeneralPartyInfo>
+ <NameInfo>
- <PersonName>
  </PersonName>
  </NameInfo>
+ <Addr>
  <AddrTypeCd>StreetAddress</AddrTypeCd>
  <Addr1>223 summer</Addr1>
  <Addr2>apt #1</Addr2>
  <City>Seattle</City>
  <StateProvCd>WA</StateProvCd>
  <PostalCode>98104</PostalCode>
  <County>KING</County>
  </Addr>
- <Communications>
- <PhoneInfo>
  <CommunicationUseCd>Home</CommunicationUseCd>
  <PhoneNumber>+1-555-5555555+123</PhoneNumber>
  </PhoneInfo>
  </Communications>
  </GeneralPartyInfo>
+ <DriverInfo>
- <PersonInfo>
  <GenderCd></GenderCd>
  <BirthDt></BirthDt>
  <MaritalStatusCd></MaritalStatusCd>
  </PersonInfo>
- <DriversLicense>
  <LicensedDt>1986-10-11</LicensedDt>
  <DriversLicenseNumber>akdfisd85226</DriversLicenseNumber>
  <FirstLicensedCurrentStateDt>1986-10-11</FirstLicensedCurrentStateDt>
  <StateProvCd>WA</StateProvCd>
  <CountryCd>US</CountryCd>
  </DriversLicense>
  </DriverInfo>
+ <PersDriverInfo VehPrincipallyDrivenRef="PersVeh1">
  <DefensiveDriverDt>2007-05-11</DefensiveDriverDt>
  <DefensiveDriverCd>N</DefensiveDriverCd>
  <DistantStudentInd>0</DistantStudentInd>
    </PersDriverInfo>
  </PersDriver>
- <PersDriver id="PersDriver2">
- <GeneralPartyInfo>
- <NameInfo>
- <PersonName>
  </PersonName>
  </NameInfo>
  </GeneralPartyInfo>
+ <DriverInfo>
- <PersonInfo>
  <GenderCd></GenderCd>
  <BirthDt></BirthDt>
  <MaritalStatusCd></MaritalStatusCd>
  <OccupationClassCd></OccupationClassCd>
  </PersonInfo>
- <DriversLicense>
  <LicensedDt>1991-05-01</LicensedDt>
  <DriversLicenseNumber>akdfisd85253</DriversLicenseNumber>
  <FirstLicensedCurrentStateDt>1991-05-01</FirstLicensedCurrentStateDt>
  <StateProvCd>WA</StateProvCd>
  <CountryCd>US</CountryCd>
  </DriversLicense>
  </DriverInfo>
+ <PersDriverInfo VehPrincipallyDrivenRef="PersVeh2">
  <DefensiveDriverDt>2007-05-11</DefensiveDriverDt>
  <DefensiveDriverCd>Y</DefensiveDriverCd>
  <DistantStudentInd>0</DistantStudentInd>
  </PersDriverInfo>
  </PersDriver>
- <PersDriver id="PersDriver3">
- <GeneralPartyInfo>
- <NameInfo>
+ <PersonName>
  </PersonName>
  </NameInfo>
  </GeneralPartyInfo>
+ <DriverInfo>
- <PersonInfo>
  <GenderCd></GenderCd>
  <BirthDt></BirthDt>
  <MaritalStatusCd></MaritalStatusCd>
  <OccupationClassCd></OccupationClassCd>
  </PersonInfo>
- <DriversLicense>
  <LicensedDt>1999-04-11</LicensedDt>
  <DriversLicenseNumber>akdfisd85251</DriversLicenseNumber>
  <FirstLicensedCurrentStateDt>1999-04-11</FirstLicensedCurrentStateDt>
  <StateProvCd>WA</StateProvCd>
  <CountryCd>US</CountryCd>
  </DriversLicense>
  </DriverInfo>
  </PersDriverInfo>
  </PersDriver>
- <PersVeh id="PersVeh1" RatedDriverRef="PersDriver1" LocationRef="Location1">
  <Manufacturer>MAZDA</Manufacturer>
  <Model>B2300 BASE/B2300 4 PK</Model>
  <ModelYear>2005</ModelYear>
  <VehBodyTypeCd>PU</VehBodyTypeCd>
.................
</PersAutoPolicyQuoteInqRq>
</InsuranceSvcRq>
</ACORD>

Thanks!

mkansal

 
Old June 14th, 2007, 01:01 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

>However, here are some of the data elements showing the 3 'PersDriver' driver elements:

You aren't iterating over the PersDriver elements, you are iterating over the PersAutoLineBusiness elements. When you do

<xsl:for-each select="a/b/c[d/e]">

then you are iterating over the c elements where the predicate d/e is satisfied. You have only one c element.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 14th, 2007, 03:14 PM
Registered User
 
Join Date: Jun 2007
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks for your response! Now I used the following:

<xsl:for-each select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver[@id]">
     <driver>
           <driver_number>
           <xsl:value-of select="substring-after(/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/@id, 'PersDriver')"/>
            </driver_number>
      </driver>
</xsl:for-each>
Now I am getting the same driver (the first one) three times. If I try the following:
<xsl:for-each select="/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver[@id=('1','2')]">
<driver>
             <driver_number>
                        <xsl:value-of select="substring-after(/ACORD/InsuranceSvcRq/PersAutoPolicyQuoteInqRq/PersAutoLineBusiness/PersDriver/@id, 'PersDriver')"/>
            </driver_number>
</driver>
It gives me TransformerException. Is the above syntax correct? I am using javax.xml.transform API. Could you please tell me if there is any other API that I can use for this purpose, which won't give this error or which jar file should I use?

Thanks again!
mkansal

 
Old June 14th, 2007, 04:49 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

For goodness sake. "It gives me TransformerException". Is that all? No other error message? If there's no other error message then you're doing something badly wrong that causes it to be suppressed. If there is another error message, then doesn't it occur to you that I might be able to help you more easily if you tell me what the error message is?

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
help in selecting elements spandit XSLT 1 April 9th, 2007 07:27 PM
Selecting unique set of elements Chamkaur XSLT 1 March 15th, 2007 05:43 AM
selecting elements from comma separated list rjonk XSLT 4 September 29th, 2006 08:46 AM
Selecting elements up until a certain one Frode XSLT 5 January 19th, 2006 01:22 PM
selecting certain xml elements fogofogo XML 2 December 5th, 2005 07:33 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.