954,568 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Help with XML parsing

This is the usual "I'm new to XSLT and need help" plea ... I am trying to parse an XML document and create a "like" structure as output while performing some mapping functions. In trying to produce the output structure, I cannot seem to figure out how to get at the element values to process. Here is a sample of the input document:

<AccountWS_AccountQueryPage_Output xmlns="urn:crmondemand/ws/account/10/2004">
    <LastPage>true</LastPage>
<ListOfAccount xmlns="urn:/crmondemand/xml/account">
      - <Account>
           <AccountId>ADOA-4FKPN1</AccountId>
           <CreatedDate>10/17/2010 20:00:24</CreatedDate>
           <Description/>
           <Location>PARIS LA DEFENSE</Location>
           <MainPhone/>
           <ModifiedDate>10/18/2010 00:02:18</ModifiedDate>
           <AccountName>AUTOMOBILES CITROEN [200000000044891]</AccountName>
           <Owner>3DS</Owner>
           <AccountType>Customer</AccountType>
           <plz_DS1_Group_Size/>
           <plz_DS1_Site_SubIndustry/>
           <plz_DS1_Site_Industry/>
           <plCompany_Country>&lt;No Values&gt;</plCompany_Country>
           <plz_DS1_Site_Type/>
           <stDUNS_Number/>
           <stDS_Company_ID>200000000044891</stDS_Company_ID>
           <stz_DS1_SIC_Code/>
           <stLeading_Channel/>
           <ParentAccountExternalSystemId/>
           <PrimaryShipToCity>PARIS LA DEFENSE</PrimaryShipToCity>
           <PrimaryShipToCountry>Canada</PrimaryShipToCountry>
           <PrimaryShipToPostalCode>92094</PrimaryShipToPostalCode>
           <PrimaryShipToProvince/>
           <PrimaryShipToState/>
           <PrimaryShipToStreetAddress>TOUR MANHATTAN</PrimaryShipToStreetAddress>
      </Account>
    <Account>
        <AccountId>ADOA-4FKPN1</AccountId>
        <CreatedDate>10/17/2010 20:00:24</CreatedDate>
        <Description/>
        <Location>PARIS LA DEFENSE</Location>
        <MainPhone/>
        <ModifiedDate>10/18/2010 00:02:18</ModifiedDate>
        <AccountName>AUTOMOBILES CITROEN [200000000044891]</AccountName>
        <Owner>3DS</Owner>
        <AccountType>Customer</AccountType>
        <plz_DS1_Group_Size/>
        <plz_DS1_Site_SubIndustry/>
        <plz_DS1_Site_Industry/>
        <plCompany_Country>Canada</plCompany_Country>
        <plz_DS1_Site_Type/>
        <stDUNS_Number/>
        <stDS_Company_ID>200000000044891</stDS_Company_ID>
        <stz_DS1_SIC_Code/>
        <stLeading_Channel/>
        <ParentAccountExternalSystemId/>
        <PrimaryShipToCity>PARIS LA DEFENSE</PrimaryShipToCity>
        <PrimaryShipToCountry>Canada</PrimaryShipToCountry>
        <PrimaryShipToPostalCode>92094</PrimaryShipToPostalCode>
        <PrimaryShipToProvince/>
        <PrimaryShipToState/>
        <PrimaryShipToStreetAddress>TOUR MANHATTAN</PrimaryShipToStreetAddress>
    </Account>
</ListOfAccount>
</AccountWS_AccountQueryPage_Output>


And the XSLT I have so far as a sample (just manipulating a few attributes for now):

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="PickLists" select="document('Picklist_data.xml')"/>
    
    <xsl:template match="*">
        <AccountWS_AccountQueryPage_Output xmlns="urn:crmondemand/ws/account/10/2004">
            <LastPage><xsl:value-of select="*:LastPage"/></LastPage>  
            <ListOfAccount xmlns="urn:/crmondemand/xml/account">            
            <xsl:variable select="*:plCompany_Country" name="plCompany_Country"/>
                
            <xsl:apply-templates select="//Account"/> 
            <xsl:for-each select="*">
            <Account>
            	<Location><xsl:value-of select="*:Location"/></Location>
                <Owner><xsl:value-of select="*:Owner"/></Owner>
                <plCompany_Country>
                <xsl:value-of
                            select="$PickLists/*:ListOfParentPicklistValue/*:ParentPicklistValue[*:ParentFieldName='plCompany_Country']/*:ListOfPicklistValue/*:PicklistValue[*:Code= $plCompany_Country]/*:DisplayValue"
                        />
                </plCompany_Country>
            </Account> 
            </xsl:for-each>
        </ListOfAccount>
   </AccountWS_AccountQueryPage_Output>
   </xsl:template>
</xsl:stylesheet>


and the output I am getting:

<?xml version="1.0" encoding="UTF-8"?>
<AccountWS_AccountQueryPage_Output xmlns="urn:crmondemand/ws/account/10/2004">
   <LastPage>true</LastPage>
   <ListOfAccount xmlns="urn:/crmondemand/xml/account">
      <Account>
         <Location/>
         <Owner/>
         <plCompany_Country/>
      </Account>
      <Account>
         <Location/>
         <Owner/>
         <plCompany_Country/>
      </Account>
   </ListOfAccount>
</AccountWS_AccountQueryPage_Output>


so in the for-each loop, I am not able to figure out exactly how to reference the values from the source document. I would greatly appreciate any advice/tips on what to do.

glfnute
Newbie Poster
7 posts since Oct 2010
Reputation Points: 10
Solved Threads: 0
 

You've got a couple conflicting ideals in this transformation. For example, you're doing an apply-templates on "//Account", but there is no "Account" node in the source document (because it's in the default namespace.)

There's some logic flaws in this, but I don't understand what the DESIRED output is supposed to look like so I can't help. Can you provide an sample DESIRED output document of what it should look like after it goes through your transformation. If I can see how things are supposed to be mapped, I'll fix it.

iceandrews
Junior Poster
185 posts since May 2010
Reputation Points: 10
Solved Threads: 30
 

First, thanks for having a look and responding. Second, sorry for the poor description. I think for what I need to do, I just want to be able to get at the values of and (we can forget about for now as I just provided it in the XSLT to show how I need to use the value for mapping with another external source document). I think if I can see how to parse all the attributes under Account while handling all the occurrences of Account I can produce my output. So, for this example, it would be a straight copy of the values. Hope this is more clear.

glfnute
Newbie Poster
7 posts since Oct 2010
Reputation Points: 10
Solved Threads: 0
 

Try this to start.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes"/>

	<xsl:variable name="PickLists" select="document('Picklist_data.xml')"/>

	<xsl:template match="/">
		<xsl:apply-templates select="*:AccountWS_AccountQueryPage_Output"/>
	</xsl:template>

	<xsl:template match="*:AccountWS_AccountQueryPage_Output">
		<xsl:copy>
			<xsl:apply-templates select="*:LastPage"/>
			<xsl:apply-templates select="*:ListOfAccount"/>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="*:ListOfAccount">
		<xsl:copy>
			<xsl:apply-templates select="*:Account"/>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="*:Account">
		<xsl:variable select="*:plCompany_Country" name="plCompany_Country"/>
		<xsl:copy>
			<xsl:apply-templates select="*:Location"/>
			<xsl:apply-templates select="*:Owner"/>
			<xsl:element name="plCompany_Country" >
				<xsl:value-of select="$PickLists/*:ListOfParentPicklistValue/*:ParentPicklistValue[*:ParentFieldName='plCompany_Country']/*:ListOfPicklistValue/*:PicklistValue[*:Code= $plCompany_Country]/*:DisplayValue"/>
			</xsl:element>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="*">
		<xsl:copy>
			<xsl:value-of select="."/>
		</xsl:copy>
	</xsl:template>
</xsl:stylesheet>
iceandrews
Junior Poster
185 posts since May 2010
Reputation Points: 10
Solved Threads: 30
 

This was of great help for me to see how to walk thru the structure. Thanks so much.

glfnute
Newbie Poster
7 posts since Oct 2010
Reputation Points: 10
Solved Threads: 0
 

Just for completeness, here is an XSL1.0 solution. A wildcard ('*') namespace prefix is not permitted in XSLT1.0. The solution is to match using the local-name() function.

xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
     <xsl:apply-templates select="*[local-name()='AccountWS_AccountQueryPage_Output']"/>
  </xsl:template>

  <xsl:template match="*[local-name()='AccountWS_AccountQueryPage_Output']">
     <xsl:copy>
        <xsl:apply-templates select="*[local-name()='LastPage']"/>
        <xsl:apply-templates select="*[local-name()='ListOfAccount']"/>
     </xsl:copy>
  </xsl:template>

  <xsl:template match="*[local-name()='ListOfAccount']">
     <xsl:copy>
        <xsl:apply-templates select="*[local-name()='Account']"/>
     </xsl:copy>
  </xsl:template>

  <xsl:template match="*[local-name()='Account']">
     <xsl:copy>
        <xsl:apply-templates select="*[local-name()='Location']"/>
        <xsl:apply-templates select="*[local-name()='Owner']"/>
     </xsl:copy>
  </xsl:template>

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

</xsl:stylesheet>
fpmurphy
Junior Poster
147 posts since Oct 2008
Reputation Points: 22
Solved Threads: 11
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: