Identity transformation problems

Discussion in 'XML' started by Bilal, Sep 25, 2006.

  1. Bilal

    Bilal Guest

    Hello,
    I'm attempting to "populate" an template XML file with some data using
    identity transform (approach suggested by Joe K.; Thanks! :) and have
    come across some strange behaviour using XMLSpy, AltovaXML, and
    xsltproc. The actual stylesheets are to be auto-generated by another
    stylesheet (that process I've worked out! :) and now troubleshooting
    these generated stylesheets in XMLSpy's XSL debugger. So I'm wondering
    if my approach is basically wrong to elicit the unexpected behaviour,
    rather than that the apps are buggy. So here goes:

    The transformation stylesheet is:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:fo="http://www.w3.org/1999/XSL/Format"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/message/Control/Trace/Id">
    <xsl:attribute name="extension">bbb-999</xsl:attribute>
    </xsl:template>
    <xsl:template match="@*|node()">
    <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>

    nothing fancy except that I'm trying to put/add value to the
    "/message/Control/Trace/Id/@extension" attribute and the xml to be
    transformed is:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <message>
    <id>Text</id>
    <creationTime>Text</creationTime>
    <versionCode/>
    <Id>Text</Id>
    <processingCode/>
    <processingModeCode/>
    <acceptCode/>
    <commRcv>
    <device>
    <id extension="Old_Ext">Text</id>
    </device>
    </commRcv>
    <commSnd>
    <device>
    <id>Text</id>
    </device>
    </commSnd>
    <Control>
    <author>
    <Entity>
    <id>Text</id>
    <code/>
    <Organization>
    <id>Text</id>
    </Organization>
    </Entity>
    </author>
    <Trace>
    <Id extension="OLD">Text</Id>
    <person>
    <value/>
    <Text>String</Text>
    </person>
    <birthTime>
    <value>Text</value>
    <Text>String</Text>
    </birthTime>
    <name>
    <value>Text</value>
    <Text>String</Text>
    </name>
    </Trace>
    </Control>
    </message>

    I'm unsure if I am doing anything illegal as far as XSL/T etc. is
    concerned but here are the results:

    XMLSpy + AltovaXML add the attribute to /message/Control/Trace instead,
    and the /message/Control/Trace/Id element isn't created at all.

    xsltproc:
    Gives the error "xsl:attribute: Cannot add attributes to an element if
    children have been already added to the element." That is very odd since
    the /message/Control/Trace/Id/ element doesn't have any children!

    I've tried various permutations of the stylesheet as follows:

    Trial #1: Populate attribute & element
    <xsl:attribute name="extension">bbb-999</xsl:attribute>
    <xsl:elementname="Id">xsl-123456789</xsl:element>

    XMLSpy/AltovaXML add the extension to the parent /message/Control/Trace
    element and the "Id" element isn't created. xsltproc errors as before.

    Trial #2: Populate element & attribute
    <xsl:elementname="Id">xsl-123456789</xsl:element>
    <xsl:attribute name="extension">bbb-999</xsl:attribute>

    XMLSpy/AltovaXML add/populate the "Id" element correctly but the
    "extension" attribute is missing. xsltproc errors as before.

    Trial #3: Populate element
    <xsl:elementname="Id">xsl-123456789</xsl:element>

    Value for "Id" element is add without problem by all.

    Trial #4: Two seperate templates
    This was my original approach but didn't work (see below). Created two
    seperate template, one for the element and one for the attribute:

    <xsl:template match="/message/Control/Trace/Id/@extension">
    <xsl:attribute
    name="extension">bbb-999</xsl:attribute> </xsl:template>
    <xsl:template match="/message/Control/Trace/Id">
    <xsl:element name="queryId">xsl-123456789</xsl:element>
    </xsl:template>

    The template for the "Id" element is actioned while the one for the
    "Id/@extension" attribute never is; unsure why the xslt processor never
    'runs' the template for the


    So what am I doing wrong??? Is there a better/proper way to populate
    both the element and its attribute?

    Would aoppreciate any suggestions! :)

    Regards,

    Bilal B.



    *** Sent via Developersdex http://www.developersdex.com ***
    Bilal, Sep 25, 2006
    #1
    1. Advertising

  2. Bilal wrote:


    > <xsl:template match="/message/Control/Trace/Id">
    > <xsl:attribute name="extension">bbb-999</xsl:attribute>
    > </xsl:template>


    That does not work out, if you want to add an attribute to that element
    then you need to first copy the element

    <xsl:template match="/message/Control/Trace/Id">
    <xsl:copy>
    <!-- use that if you have other attributes to copy -->
    <xsl:apply-templates select="@*"/>
    <xsl:attribute name="extension">bbb-999</xsl:attribute>
    <xsl:apply-templates/>
    </xsl:copy>
    </xsl:template>


    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
    Martin Honnen, Sep 25, 2006
    #2
    1. Advertising

  3. Bilal

    Bilal Guest

    Hi Martin,
    Many thanks!! That works for adding/setting the attribute but what if
    the element's value is also being set simultaneously?

    Regards,

    Bilal



    *** Sent via Developersdex http://www.developersdex.com ***
    Bilal, Sep 25, 2006
    #3
  4. Bilal wrote:


    > That works for adding/setting the attribute but what if
    > the element's value is also being set simultaneously?


    Well once you write a template for that element it is up to you to fill
    the template with instructions as needed, the xsl:copy will only copy
    the element itself, the <xsl:apply-templates select="@*"/> (and the
    other template you had) take care of copying existing attributes, the
    <xsl:attribute name="extension">bbb-999</xsl:attribute> adds the new
    attribute, and the <xsl:apply-templates/> lets the XSLT processor
    process the existing child nodes. If you don't want any of those steps
    then remove or replace them e.g.

    <xsl:template match="/message/Control/Trace/Id">
    <xsl:copy>
    <!-- use that if you have other attributes to copy -->
    <xsl:apply-templates select="@*"/>
    <xsl:attribute name="extension">bbb-999</xsl:attribute>
    <xsl:text>Kibology for all</xsl:text>
    </xsl:copy>
    </xsl:template>

    will not process the child nodes but simply add that (example) text as a
    child node.

    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
    Martin Honnen, Sep 25, 2006
    #4
  5. Bilal

    Bilal Guest

    Hi Martin,
    Thanks for the explanation and the example. Unfortunately, I still
    don't have a full understanding about the 'precedence' of how the
    templates are applied, and hence in my not-so-infiite wisdom, I was
    trying to use the code below (note the xsl:element tag instead of the
    xsl:text tag) to put value in the Id element itself, and kept on
    wondering why it was adding an new element /message/Control/Trace/Id/Id
    instead :-(

    <xsl:template match="/message/Control/Trace/Id">
    <xsl:copy>
    <!-- use that if you have other attributes to copy -->
    <xsl:apply-templates select="@*"/>
    <xsl:attribute name="extension">bbb-999</xsl:attribute>
    <xsl:element name="Id">Kibology for all</xsl:element>
    </xsl:copy>
    </xsl:template>

    Just to take this one step further, what would be the right way to copy
    the children below /message/Control/Trace/Id using the default template?

    <xsl:template match="/message/Control/Trace/Id">
    <xsl:copy>
    <!-- use that if you have other attributes to copy -->
    <xsl:apply-templates select="@*"/>
    <xsl:attribute name="extension">bbb-999</xsl:attribute>
    <xsl:text>Kibology for all</xsl:text>
    <xsl:apply-templates />
    </xsl:copy>
    </xsl:template>

    This appears to do the trick (I think) but what it ALSO does is copy the
    old text value (child?) AFTER inserting the new text value, as well as
    copying any remaining child elements.
    How would one achieve copying the new text value/child, avoid copying
    the old text value/child, but copy any child elements?

    Lastly, any recommendations on good XSL resources/books other then
    obvious ones on the web? I think I'm reaching the limits of my
    self-learned XSLT knowledge.

    Regards,

    Bilal B.

    *** Sent via Developersdex http://www.developersdex.com ***
    Bilal, Sep 26, 2006
    #5
  6. Bilal wrote:


    > Unfortunately, I still
    > don't have a full understanding about the 'precedence' of how the
    > templates are applied, and hence in my not-so-infiite wisdom, I was
    > trying to use the code below (note the xsl:element tag instead of the
    > xsl:text tag) to put value in the Id element itself, and kept on
    > wondering why it was adding an new element /message/Control/Trace/Id/Id
    > instead :-(
    >
    > <xsl:template match="/message/Control/Trace/Id">


    You have a template here for Id elements with parent Trace with parent
    Control with parent message as the root element, then in that template
    you do

    > <xsl:copy>


    meaning that Id element is copied. If you don't want to copy those Id
    elements then don't use xsl:copy in this template. But if you want to
    have attributes like that extension attribute you first need an element
    to add it to.


    > How would one achieve copying the new text value/child, avoid copying
    > the old text value/child, but copy any child elements?


    Sorry, in my understanding you can't "copy" "new" values or children,
    "new" stuff can only be added.
    As for copying only child _elements_ but not child _text_ nodes simply
    do e.g.
    <xsl:apply-templates select="*"/>
    instead of
    <xsl:apply-templates/>
    in the template where you want to do that. For the rare case that you
    also have comment nodes or processing instruction nodes that need to be
    copied like the elements then do e.g.
    <xsl:apply-templates select="node()[self::* or self::comment() or
    self::processing-instruction()]"/>




    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
    Martin Honnen, Sep 26, 2006
    #6
  7. Bilal wrote:
    > don't have a full understanding about the 'precedence' of how the
    > templates are applied


    There are almost no precedence rules, unfortunately. If you've got a
    possible conflict, you should probably make your precedence explicit by
    adding the priority attribute to the templates in question.

    > How would one achieve copying the new text value/child, avoid copying
    > the old text value/child, but copy any child elements?


    One solution: Change the select in the second apply-templates so it
    matches only elements. "*" will work, since the implied axis is child
    and the principal node type of that axis is element. If you wanted to
    accept other kinds of non-text nodes you might want to enhance that a
    bit, eg "*|comment()".

    Another solution would be to use a mode, but that's a bit more
    complicated to explain if you aren't already familiar with them.

    > Lastly, any recommendations on good XSL resources/books other then
    > obvious ones on the web? I think I'm reaching the limits of my
    > self-learned XSLT knowledge.


    I haven't looked at what's come out recently. Mike Kay's tome is still
    the best XSLT reference manual out there, I think, but if you're looking
    for a tutorial you'll want something else as well.

    --
    () ASCII Ribbon Campaign | Joe Kesselman
    /\ Stamp out HTML e-mail! | System architexture and kinetic poetry
    Joe Kesselman, Sep 26, 2006
    #7
  8. Bilal

    Bilal Guest

    Hi Joe and Martin,
    Thanks for the replies; your explanation/examples helped solve the
    problem I had been stuck!

    Many thanks! :)

    Regards,

    Bilal B.


    *** Sent via Developersdex http://www.developersdex.com ***
    Bilal, Sep 27, 2006
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Giovanni Bassi
    Replies:
    0
    Views:
    638
    Giovanni Bassi
    Oct 20, 2003
  2. nalbayo
    Replies:
    2
    Views:
    5,491
    Bruce Barker
    Nov 11, 2005
  3. Chris Bedford
    Replies:
    1
    Views:
    668
    Ben Edgington
    May 21, 2004
  4. JimLad
    Replies:
    0
    Views:
    444
    JimLad
    Jan 16, 2009
  5. Frederick D'hont
    Replies:
    0
    Views:
    306
    Frederick D'hont
    Jul 25, 2005
Loading...

Share This Page