XSLT Logic Problem

Here should go questions about transforming XML with XSLT and FOP.
cyoull
Posts: 2
Joined: Fri Jul 19, 2013 12:08 am

XSLT Logic Problem

Post by cyoull »

HI,
I am having some logic problems transforming an XML document. I thought I had it correct until a new <app_id> was added to the XML document and I had duplicate data in my output.

This is a sample of the XML

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<cc_info>
<file_header>
<app_id>1407</app_id>
<total_of_sale_amounts>36400.00</total_of_sale_amounts>
</file_header>
<card_type_item>
<cc_type>AmericanExpress</cc_type>
<total_sale>1960.00</total_sale>
<body_item>
<cc_no>0009</cc_no>
<customer_name>Customer 09</customer_name>
<payment_amount>1400.00</payment_amount>
<event_type>Sale</event_type>
<custom_collection_field>
<name>serial _number</name>
<value>IMC182097</value>
</custom_collection_field>
<custom_collection_field>
<name>cost_center_state</name>
<value>1006</value>
</custom_collection_field>
</body_item>
<body_item>
<cc_no>0008</cc_no>
<customer_name>Customer 08</customer_name>
<payment_amount>2000.00</payment_amount>
<event_type>Sale</event_type>
<custom_collection_field>
<name>serial _number</name>
<value>UMC364967</value>
</custom_collection_field>
<custom_collection_field>
<name>cost_center_state</name>
<value>UT</value>
</custom_collection_field>
</body_item>
</card_type_item>

<!-- For Testing - Adding this additional app_id duplicates the body elements under the new app_id

<file_header>
<app_id>1240</app_id>
<total_of_sale_amounts>0.00</total_of_sale_amounts>
</file_header>
<card_type_item>
<cc_type></cc_type>
<total_sale>0.00</total_sale>
<total_credited>0.00</total_credited>
<total_voided>0.00</total_voided>
<total_failed>0.00</total_failed>
<total_authorization>0.00</total_authorization>
<count_sale>0</count_sale>
<count_credited>0</count_credited>
<count_voided>0</count_voided>
<count_failed>0</count_failed>
<count_authorization>0</count_authorization>
<body_item>
<cc_no></cc_no>
<customer_name></customer_name>
<payment_amount></payment_amount>
<event_type></event_type>
</body_item>
</card_type_item>
-->
<file_footer>
<file_name>ActivityFile_07112013.xml</file_name>
<file_creation_date>2013-07-15T17:07:28</file_creation_date>
</file_footer>
</cc_info>
This is the XSLT that I created

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
version="2.0">

<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="cc_info/file_header"/>

</xsl:template>
<xsl:template match="file_header">
SOURCE_SYSTEM=<xsl:value-of select="app_id"/>
<xsl:apply-templates select="../card_type_item/body_item"/>

</xsl:template>
<xsl:template match="body_item">
Customer Name=<xsl:value-of select="customer_name"/>
Payment Amount=<xsl:value-of select="payment_amount"/>
</xsl:template>

</xsl:stylesheet>
This is the result when only one <app_id> is in the XML
SOURCE_SYSTEM=1407
Customer Name=Customer 09
Payment Amount=1400.00
Customer Name=Customer 08
Payment Amount=2000.00

When I remove the comment section to add an additional <file_header> in the XML document, the customer name and payment amount duplicate under the added <app_id>

SOURCE_SYSTEM=1407
Customer Name=Customer 09
Payment Amount=1400.00
Customer Name=Customer 08
Payment Amount=2000.00
Customer Name=
Payment Amount=
SOURCE_SYSTEM=1240
Customer Name=Customer 09
Payment Amount=1400.00
Customer Name=Customer 08
Payment Amount=2000.00
Customer Name=
Payment Amount=

What I wanted to achieve was this:

SOURCE_SYSTEM=1407
Customer Name=Customer 09
Payment Amount=1400.00
Customer Name=Customer 08
Payment Amount=2000.00
SOURCE_SYSTEM=1240
Customer Name=
Payment Amount=

I am not sure what changes are necessary in the XSLT to obtain the desired results. Any help would be appreciated.
adrian
Posts: 2883
Joined: Tue May 17, 2005 4:01 pm

Re: XSLT Logic Problem

Post by adrian »

Hi,

The mistake is in the file_header template:

Code: Select all

<xsl:apply-templates select="../card_type_item/body_item"/>
This selects all the "card_type_item" elements, not just the one that follows the "file_header" element.

Assuming that the elements "file_header" and "card_type_item" come in pairs (as in your example), you can use the position of the "file_header" element to point to the corresponding "card_type_item" element.

Code: Select all

    <xsl:template match="file_header">
<xsl:variable name="pos" select="position()"/>
SOURCE_SYSTEM=<xsl:value-of select="app_id"/>
<xsl:apply-templates select="../card_type_item[$pos]/body_item"/>
</xsl:template>
Also, on another note, if you want your output text to be aligned to the left (without being indented), surround it with <xsl:text>.
e.g.

Code: Select all

<xsl:text>SOURCE_SYSTEM=</xsl:text>
Regards,
Adrian
Adrian Buza
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com
Post Reply