XSLT preceding problem

S

Sven

Hi

I have the following XML & XSLT:

XML:
<?xml version="1.0" encoding="utf-8"?>

<Source Source="IBM">
<Detail>
<UserID></UserID>
<Time>20030610135531</Time>
<ActionCode>IBM421</ActionCode>
<ActionText>Start sessie</ActionText>
<ChargingID>0750490000011325</ChargingID>
</Detail>

<Detail>
<UserID>31622000658</UserID>
<Time>20030610135532</Time>
<ActionCode>IBM420</ActionCode>
<ActionText>Succesvolle account balance wijziging</ActionText>
<ChargingID>0750490000011325</ChargingID>
</Detail>

<Detail>
<UserID>time-trigger</UserID>
<Time>20030613235901</Time>
<ActionCode>IBM440</ActionCode>
<ActionText>rapport 1</ActionText>
<ChargingID></ChargingID>
</Detail>

<Detail>
<UserID>time-trigger</UserID>
<Time>20030613235902</Time>
<ActionCode>IBM443</ActionCode>
<ActionText>Rapport 3</ActionText>
<ChargingID></ChargingID>
</Detail>

</Source>


XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" version="1.0" encoding="ISO-8859-1"
indent="yes"/>

xsl:param name="action_codes" select="',420,421,422,430,431,432,'"/>
<xsl:template match="/">

<xsomething>
<data_details>
<xsl:for-each select="Source/Detail[(contains($action_codes,concat(',',substring(ActionCode,4,3),',')))]">
<xsl:sort select="Time" order="ascending"/>

<data_detail>
<xsl:if test="string-length(UserID) != 0">
<user_id><xsl:value-of select="UserID"/></user_id>
</xsl:if>

<datum_record>
<xsl:value-of select="substring(Time,1, 4)"/>-<xsl:value-of
select="substring(Time, 5, 2)"/>-<xsl:value-of select="substring(Time,
7, 2)"/>T<xsl:value-of select="substring(Time, 9, 2)"/>:<xsl:value-of
select="substring(Time, 11, 2)"/>:<xsl:value-of
select="substring(Time, 13, 2)"/>
</datum_record>

<action_code><xsl:value-of select="ActionCode"/></action_code>

<action_tekst><xsl:value-of select="ActionText"/></action_tekst>

<xsl:if test="string-length(ChargingID) != 0">
<charging_id><xsl:value-of select="ChargingID"/></charging_id>
</xsl:if>

<xsl:if test="string-length(ChargingID) = 0">
<charging_id><xsl:value-of
select="normalize-space(preceding::ChargingID[1])"/></charging_id>
</xsl:if>
</data_detail>

</xsl:for-each>
</data_details>
</xsomething>

</xsl:template>
</xsl:stylesheet>

The goal of my xslt is, that when the tag CHARGING_ID is missing that
the previously known charging_id will be used. Sometimes it will be
the previous another time it will be 10 'records' back.

Unfortunately the XSLT above is not working correctly, because when
the value of Charging_id is not present the tag will be supplied (I
cannot change it).

Is there another way to achieve my goal, by ie. changing this piece of
code 'preceding::ChargingID[1]'?
I have tried recursive templates but I didnt figured it out ?

Anyone an idea ?

greets
Sven
 
M

Marrow

Hi Sven,

I think you are almost there...

If you change...
<xsl:value-of select="normalize-space(preceding::ChargingID[1])"/>
to...
<xsl:value-of select="preceding::ChargingID[normalize-space()][1]"/>

Although rather than two opposing <xsl:if>'s you might be better with a
<xsl:choose>, e.g.

<charging_id>
<xsl:choose>
<xsl:when test="normalize-space(ChargingID)">
<xsl:value-of select="ChargingID"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of
select="preceding::ChargingID[normalize-space()][1]"/>
</xsl:eek:therwise>
</xsl:choose>
</charging_id>

Or you could roll it into one XPath expression, something like...

<charging_id>
<xsl:value-of select="(ChargingID[normalize-space()] |
preceding-sibling::Detail[normalize-space(ChargingID)][1]/ChargingID)[last()
]"/>
</charging_id>

BTW, if you replace this bit of code...

<datum_record>
<xsl:value-of select="substring(Time,1, 4)"/>-<xsl:value-of
select="substring(Time, 5, 2)"/>-<xsl:value-of select="substring(Time,
7, 2)"/>T<xsl:value-of select="substring(Time, 9, 2)"/>:<xsl:value-of
select="substring(Time, 11, 2)"/>:<xsl:value-of
select="substring(Time, 13, 2)"/>
</datum_record>

with...

<datum_record>
<xsl:value-of select="substring(Time,1, 4)"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="substring(Time, 5, 2)"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="substring(Time, 7, 2)"/>
<xsl:text>T</xsl:text>
<xsl:value-of select="substring(Time, 9, 2)"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="substring(Time, 11, 2)"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="substring(Time, 13, 2)"/>
</datum_record>

you won't have to run all the lines of XSLT code together in order to avoid
CR/LFs from appearing in the <datum_record> output element value.

Hope this helps
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator


Sven said:
Hi

I have the following XML & XSLT:

XML:
<?xml version="1.0" encoding="utf-8"?>

<Source Source="IBM">
<Detail>
<UserID></UserID>
<Time>20030610135531</Time>
<ActionCode>IBM421</ActionCode>
<ActionText>Start sessie</ActionText>
<ChargingID>0750490000011325</ChargingID>
</Detail>

<Detail>
<UserID>31622000658</UserID>
<Time>20030610135532</Time>
<ActionCode>IBM420</ActionCode>
<ActionText>Succesvolle account balance wijziging</ActionText>
<ChargingID>0750490000011325</ChargingID>
</Detail>

<Detail>
<UserID>time-trigger</UserID>
<Time>20030613235901</Time>
<ActionCode>IBM440</ActionCode>
<ActionText>rapport 1</ActionText>
<ChargingID></ChargingID>
</Detail>

<Detail>
<UserID>time-trigger</UserID>
<Time>20030613235902</Time>
<ActionCode>IBM443</ActionCode>
<ActionText>Rapport 3</ActionText>
<ChargingID></ChargingID>
</Detail>

</Source>


XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" version="1.0" encoding="ISO-8859-1"
indent="yes"/>

xsl:param name="action_codes" select="',420,421,422,430,431,432,'"/>
<xsl:template match="/">

<xsomething>
<data_details>
<xsl:for-each select="Source/Detail[(contains($action_codes,concat(',',substring(ActionCod
e,4,3),',')))]">
<xsl:sort select="Time" order="ascending"/>

<data_detail>
<xsl:if test="string-length(UserID) != 0">
<user_id><xsl:value-of select="UserID"/></user_id>
</xsl:if>

<datum_record>
<xsl:value-of select="substring(Time,1, 4)"/>-<xsl:value-of
select="substring(Time, 5, 2)"/>-<xsl:value-of select="substring(Time,
7, 2)"/>T<xsl:value-of select="substring(Time, 9, 2)"/>:<xsl:value-of
select="substring(Time, 11, 2)"/>:<xsl:value-of
select="substring(Time, 13, 2)"/>
</datum_record>

<action_code><xsl:value-of select="ActionCode"/></action_code>

<action_tekst><xsl:value-of select="ActionText"/></action_tekst>

<xsl:if test="string-length(ChargingID) != 0">
<charging_id><xsl:value-of select="ChargingID"/></charging_id>
</xsl:if>

<xsl:if test="string-length(ChargingID) = 0">
<charging_id><xsl:value-of
select="normalize-space(preceding::ChargingID[1])"/></charging_id>
</xsl:if>
</data_detail>

</xsl:for-each>
</data_details>
</xsomething>

</xsl:template>
</xsl:stylesheet>

The goal of my xslt is, that when the tag CHARGING_ID is missing that
the previously known charging_id will be used. Sometimes it will be
the previous another time it will be 10 'records' back.

Unfortunately the XSLT above is not working correctly, because when
the value of Charging_id is not present the tag will be supplied (I
cannot change it).

Is there another way to achieve my goal, by ie. changing this piece of
code 'preceding::ChargingID[1]'?
I have tried recursive templates but I didnt figured it out ?

Anyone an idea ?

greets
Sven
 
S

Sven

Hi Marrow,

Thank you very much. It works excellent !! Also thanx for the addiditional remarks.

greets,
Sven
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top