XSLT - How to transform Element to Attribute?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • SPanicker
    New Member
    • Dec 2008
    • 16

    XSLT - How to transform Element to Attribute?

    Hi,

    I am newbie to XSL transformations . I am finding it hard to work out the XSL transformation for the following XML. Can someone suggest me how to approach this XML or in general how should I start up if given a XML?

    SOURCE XML:

    Code:
    <?xml version="1.0" encoding="iso-8859-1"?>
    <Batch BatchCreated="" TransType="TA" xmlns="http://www.w3.org/2001/xmlns">
    <TA>
    <Id>111</Id>
    <recipient>ABC Corp.</recipient>
    </TA>
    <CL>
    <id>12123</id>
    <claimNumber>1023-1</claimNumber>
    <code>Other</code>
    <dateReceived>01/24/2007 14:18:50</dateReceived>
    <policyLimit>352,000</policyLimit>
    <covName>Building</covName>
    </CL>
    <Contacts>
    <Insured>
    <type>client</type>
    <InsName>JOHN</InsName>
    <street>12 WALKER ST</street>
    <city>SIGMUND PARK</city>
    <state>KS</state>
    <country>US</country>
    <postal>67208</postal>
    <InsHomeNumber>1212151423</InsHomeNumber>
    <InsWorkNumber>55221155213</InsWorkNumber>
    <WorkExtn>123</WorkExtn>
    </Insured>
    <Claimant>
    <type>claimant</type>
    <name>MARK</name>
    </Claimant>
    </Contacts>
    </Batch>
    TRANSFORMED FINAL XML (what i need):

    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <INFO>
    <TA recipient="ABC Corp." Id="111" />
    <CONTACTS>
    <CONTACT type="Client" name="JOHN">
    <ADDRESSES>
    <ADDRESS type="Property" city="SIGMUND PARK" street=">12 WALKER ST" state="KS" postal="67208" country="US" />
    </ADDRESSES>
    <CONTACTMETHODS>
    <PHONE type="Home" number="1212151423" extension="" />
    <PHONE type="Business" number="55221155213" extension="123" />
    </CONTACTMETHODS>
    </CONTACT>
    <CONTACT type="Claimant" name="MARK" />
    </CONTACTS>
    <LOSSDETAILS dateReceived="2007-01-24T14:18:50">
    <LOSS claimNumber="1023-1">
    <COVERAGES>
    <COVERAGE id="12123" covName="Building" policyLimit="3520000" />
    </COVERAGES>
    <TOL desc="Other" code="Other"></TOL>
    </LOSS>
    </LOSSDETAILS>
    </INFO>
    Regards,
    SP.
  • Dormilich
    Recognized Expert Expert
    • Aug 2008
    • 8694

    #2
    basicly you need to figure out, which data structure from the input belong to which data structure in the output. use xslt to a) get the data from the former and b) write the data to the latter.

    best explained in an example. let's take the <ta> tag from the input
    Code:
    <TA>
    <Id>111</Id>
    <recipient>ABC Corp.</recipient>
    </TA>
    this will be the following in the output:
    Code:
    <TA recipient="ABC Corp." Id="111" />
    so the <recipient> tag goes to the recipient attribute (same for id)
    to put this into XSL
    Code:
    <xsl:template match="w3c:TA">
      <TA recipient="{w3c:recipient/text()}" Id="{w3c:Id/text()}"/>
    </xsl:template>
    what does that mean:
    • w3c:TA
      the element <TA> with its namespace (the one you defined in the <Batch> element (you can choose any namespace prefix you like).
      the template will be called if the TA node is processed
    • recipient="{w3c :recipient/text()}"
      write an attribute named "recipient" and write its content as computed from the text node of the <recipient> child node (again with namespace)

    this way you can write each target element.

    start the whole whole process
    Code:
    <xsl:template match="/">
      <xsl:apply-templates/>
    </xsl:template>
    don't forget to define your namespace:
    Code:
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:w3c="http://www.w3.org/2001/xmlns">
    regards

    Comment

    • SPanicker
      New Member
      • Dec 2008
      • 16

      #3
      Hi Dormilich,

      That was great !

      Hope I can start up with this basic idea.

      Will post bak if I get stuck up.Thnx :-) .


      Regards,
      SP.

      Comment

      • SPanicker
        New Member
        • Dec 2008
        • 16

        #4
        Hi,

        Referring to my previous post - how can i apply a separate template (styling) for an child element inside <xsl:template >?

        For eg., if I need to apply a separate template for the contact of type 'Claimant' how can I do that?

        This was what I trying but it changes the hierarchy of the XML:

        Code:
          <xsl:template match ="Insured">
            <CONTACTS>
              <CONTACT type="{type/text()}" name="{name/text()}">
                <ADDRESSES>
                  <ADDRESS type="property" city="{city/text()}" street="{street/text()}" state="{state/text()}" postal="{postal/text()}" country="US">            
                  </ADDRESS>
                  <CONTACTMETHODS>
                    <PHONE type="Home" number="{HomeNumber/text()}"></PHONE>
                    <PHONE type="Business" number="{WorkNumber/text()}" extension="{WorkExt/text()}"></PHONE>
                  </CONTACTMETHODS>
                </ADDRESSES>
              </CONTACT>
              <xsl:apply-templates select ="Claimant"></xsl:apply-templates>
            </CONTACTS>    
          </xsl:template>
            
          <xsl:template match ="Claimant">
            <CONTACT type="{type/text()}" name="{name/text()}">
              </CONTACT>
          </xsl:template>
        This is causing the second <CONTACT> element to be a child of the root element rather than being the child of <CONTACTS>.

        Comment

        • Dormilich
          Recognized Expert Expert
          • Aug 2008
          • 8694

          #5
          you could try a named template.

          regards

          Comment

          • SPanicker
            New Member
            • Dec 2008
            • 16

            #6
            Can you quote some example?

            Regards,
            SP.

            Comment

            • Dormilich
              Recognized Expert Expert
              • Aug 2008
              • 8694

              #7
              sure
              Named Template Example

              regards

              Comment

              • SPanicker
                New Member
                • Dec 2008
                • 16

                #8
                Thnx.

                Regards,
                SP.

                Comment

                • SPanicker
                  New Member
                  • Dec 2008
                  • 16

                  #9
                  Hi,

                  Is there any other way to do this? I had been trying to achieve the above XML for a while and nothing helped me out.

                  Any suggestions on how to implement it?

                  Comment

                  • jkmyoung
                    Recognized Expert Top Contributor
                    • Mar 2006
                    • 2057

                    #10
                    My guess is you'd need apply-templates to get the elements in the same order. Wasn't going to post this, since it didn't totally apply but anyways:

                    generic element -> attribute template
                    [code=xml]
                    <?xml version="1.0" encoding="UTF-8"?>
                    <xsl:styleshe et version="1.0" xmlns:xsl="http ://www.w3.org/1999/XSL/Transform"/>
                    <xsl:template match="*">
                    <xsl:copy>
                    <xsl:for-each select="*[not(*)]">
                    <xsl:attribut e name="{name()}" ><xsl:value-of select="."/></xsl:attribute>
                    </xsl:for-each>
                    <xsl:apply-templates select="*[*]"/>
                    </xsl:copy>
                    </xsl:template>
                    </xsl:stylesheet>
                    [/code]
                    Specific to your problem:
                    1. Since you're getting rid of the namespace, replace
                    <xsl:copy> with <xsl:element name="local-name()">

                    2. Remove unnecessary nodes: eg CL, etc... seperated by |
                    <xsl:template match="CL|Other Node|etc"/>

                    3. Have custom templates accordingly:
                    [code=xml]
                    xmlns:w3="http://www.w3.org/2001/xmlns"
                    ...
                    <xsl:template match="w3:Batch ">
                    <INFO>
                    <xsl:apply-templates/>
                    </INFO>
                    </xsl:template>
                    <xsl:template match ="w3:Claiman t">
                    <CONTACT type="{type/text()}" name="{name/text()}"/>
                    </xsl:template>
                    <xsl:template match="w3:Insur ed"><!-- remove this node, but continue on. -->
                    <xsl:apply-templates/>
                    </xsl:template>
                    [/code]

                    Don't know where you're getting loss details from. Assuming it's somewhere else in unposted source code.

                    Comment

                    Working...