XSLT preceding problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Sven

    #1

    XSLT preceding problem

    Hi

    I have the following XML & XSLT:

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

    <Source Source="IBM">
    <Detail>
    <UserID></UserID>
    <Time>200306101 35531</Time>
    <ActionCode>IBM 421</ActionCode>
    <ActionText>Sta rt sessie</ActionText>
    <ChargingID>075 0490000011325</ChargingID>
    </Detail>

    <Detail>
    <UserID>3162200 0658</UserID>
    <Time>200306101 35532</Time>
    <ActionCode>IBM 420</ActionCode>
    <ActionText>Suc cesvolle account balance wijziging</ActionText>
    <ChargingID>075 0490000011325</ChargingID>
    </Detail>

    <Detail>
    <UserID>time-trigger</UserID>
    <Time>200306132 35901</Time>
    <ActionCode>IBM 440</ActionCode>
    <ActionText>rap port 1</ActionText>
    <ChargingID></ChargingID>
    </Detail>

    <Detail>
    <UserID>time-trigger</UserID>
    <Time>200306132 35902</Time>
    <ActionCode>IBM 443</ActionCode>
    <ActionText>Rap port 3</ActionText>
    <ChargingID></ChargingID>
    </Detail>

    </Source>


    XSLT:

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

    xsl:param name="action_co des" select="',420,4 21,422,430,431, 432,'"/>
    <xsl:template match="/">

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

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

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

    <action_code><x sl:value-of select="ActionC ode"/></action_code>

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

    <xsl:if test="string-length(Charging ID) != 0">
    <charging_id><x sl:value-of select="Chargin gID"/></charging_id>
    </xsl:if>

    <xsl:if test="string-length(Charging ID) = 0">
    <charging_id><x sl:value-of
    select="normali ze-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::Cha rgingID[1]'?
    I have tried recursive templates but I didnt figured it out ?

    Anyone an idea ?

    greets
    Sven
  • Marrow

    #2
    Re: XSLT preceding problem

    Hi Sven,

    I think you are almost there...

    If you change...
    <xsl:value-of select="normali ze-space(preceding ::ChargingID[1])"/>
    to...
    <xsl:value-of select="precedi ng::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(ChargingI D)">
    <xsl:value-of select="Chargin gID"/>
    </xsl:when>
    <xsl:otherwis e>
    <xsl:value-of
    select="precedi ng::ChargingID[normalize-space()][1]"/>
    </xsl:otherwise>
    </xsl:choose>
    </charging_id>

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

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

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

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

    with...

    <datum_record >
    <xsl:value-of select="substri ng(Time,1, 4)"/>
    <xsl:text>-</xsl:text>
    <xsl:value-of select="substri ng(Time, 5, 2)"/>
    <xsl:text>-</xsl:text>
    <xsl:value-of select="substri ng(Time, 7, 2)"/>
    <xsl:text>T</xsl:text>
    <xsl:value-of select="substri ng(Time, 9, 2)"/>
    <xsl:text>:</xsl:text>
    <xsl:value-of select="substri ng(Time, 11, 2)"/>
    <xsl:text>:</xsl:text>
    <xsl:value-of select="substri ng(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" <sven@it4us.n l> wrote in message
    news:6ab307b9.0 307070544.15349 b9a@posting.goo gle.com...[color=blue]
    > Hi
    >
    > I have the following XML & XSLT:
    >
    > XML:
    > <?xml version="1.0" encoding="utf-8"?>
    >
    > <Source Source="IBM">
    > <Detail>
    > <UserID></UserID>
    > <Time>200306101 35531</Time>
    > <ActionCode>IBM 421</ActionCode>
    > <ActionText>Sta rt sessie</ActionText>
    > <ChargingID>075 0490000011325</ChargingID>
    > </Detail>
    >
    > <Detail>
    > <UserID>3162200 0658</UserID>
    > <Time>200306101 35532</Time>
    > <ActionCode>IBM 420</ActionCode>
    > <ActionText>Suc cesvolle account balance wijziging</ActionText>
    > <ChargingID>075 0490000011325</ChargingID>
    > </Detail>
    >
    > <Detail>
    > <UserID>time-trigger</UserID>
    > <Time>200306132 35901</Time>
    > <ActionCode>IBM 440</ActionCode>
    > <ActionText>rap port 1</ActionText>
    > <ChargingID></ChargingID>
    > </Detail>
    >
    > <Detail>
    > <UserID>time-trigger</UserID>
    > <Time>200306132 35902</Time>
    > <ActionCode>IBM 443</ActionCode>
    > <ActionText>Rap port 3</ActionText>
    > <ChargingID></ChargingID>
    > </Detail>
    >
    > </Source>
    >
    >
    > XSLT:
    >
    > <?xml version="1.0" encoding="UTF-8"?>
    > <xsl:styleshe et version="1.0"
    > xmlns:xsl="http ://www.w3.org/1999/XSL/Transform">
    > <xsl:output method="xml" version="1.0" encoding="ISO-8859-1"
    > indent="yes"/>
    >
    > xsl:param name="action_co des" select="',420,4 21,422,430,431, 432,'"/>
    > <xsl:template match="/">
    >
    > <xsomething>
    > <data_details >
    > <xsl:for-each[/color]
    select="Source/Detail[(contains($acti on_codes,concat (',',substring( ActionCod
    e,4,3),',')))]">[color=blue]
    > <xsl:sort select="Time" order="ascendin g"/>
    >
    > <data_detail>
    > <xsl:if test="string-length(UserID) != 0">
    > <user_id><xsl:v alue-of select="UserID"/></user_id>
    > </xsl:if>
    >
    > <datum_record >
    > <xsl:value-of select="substri ng(Time,1, 4)"/>-<xsl:value-of
    > select="substri ng(Time, 5, 2)"/>-<xsl:value-of select="substri ng(Time,
    > 7, 2)"/>T<xsl:value-of select="substri ng(Time, 9, 2)"/>:<xsl:value-of
    > select="substri ng(Time, 11, 2)"/>:<xsl:value-of
    > select="substri ng(Time, 13, 2)"/>
    > </datum_record>
    >
    > <action_code><x sl:value-of select="ActionC ode"/></action_code>
    >
    > <action_tekst>< xsl:value-of select="ActionT ext"/></action_tekst>
    >
    > <xsl:if test="string-length(Charging ID) != 0">
    > <charging_id><x sl:value-of select="Chargin gID"/></charging_id>
    > </xsl:if>
    >
    > <xsl:if test="string-length(Charging ID) = 0">
    > <charging_id><x sl:value-of
    > select="normali ze-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::Cha rgingID[1]'?
    > I have tried recursive templates but I didnt figured it out ?
    >
    > Anyone an idea ?
    >
    > greets
    > Sven[/color]


    Comment

    • Sven

      #3
      Re: XSLT preceding problem

      Hi Marrow,

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

      greets,
      Sven

      "Marrow" <marrow-NO-@-SPAM-marrowsoft.com> wrote in message news:<GXfOa.947 $%I5.676@newsfe p3-gui.server.ntli .net>...[color=blue]
      > Hi Sven,
      >
      > I think you are almost there...
      >[/color]

      Comment

      Working...