1

i have a Source XML which looks like this

<parent>
      <child id="123456">Child Name
      </child>
      <image name="child.jpg">
</parent>

The destination XML should be

<data>
     <person id="123456">
        <name>Child Name</name>
     </person>
     <relation id="123456">
        <filename>child.jpg</filename>
     </relation>
</data>

I am using XSLT to transform this. The Problem is that when how can i get the value of id (which is 123456) from in source XML at two different places in Destination XML using XSLT.

1
  • @dradu: It isn't necessary to use variables in solving this problem -- see my answer. Commented May 14, 2012 at 13:16

2 Answers 2

2

Here is a short and simple solution:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="parent">
     <data>
       <xsl:apply-templates/>
     </data>
 </xsl:template>

 <xsl:template match="child">
  <person id="{@id}">
    <name><xsl:value-of select="."/></name>
  </person>
 </xsl:template>

 <xsl:template match="image">
  <relation id="{preceding-sibling::child[1]/@id}">
   <filename><xsl:value-of select="@name"/></filename>
  </relation>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<parent>
    <child id="123456">Child Name</child>
    <image name="child.jpg"/>
</parent>

the wanted, correct result is produced:

<data>
   <person id="123456">
      <name>Child Name</name>
   </person>
   <relation id="123456">
      <filename>child.jpg</filename>
   </relation>
</data>
Sign up to request clarification or add additional context in comments.

3 Comments

@Touseef: What you cite as "simple" is unnecessarily complicated (no xsl:element and no xsl:attribute' is necessary), inefficient and potentially buggy (ancestor::MainStory/@kmsid` scans all ancestors and generally selects more than one node).
Thanks Dimitre, it was helping
@Touseef: I am glad my answer was useful to you. Could you, please, accept this answer (by clicking on the check-mark next to the answer)?
0

You may try this: The XSL:

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
    <data>
        <xsl:for-each select="parent">
            <!--variable to store @id-->
            <xsl:variable name="id" select="child/@id"/>
            <!--creating a test comment node()-->
            <xsl:comment>Child having id: <xsl:value-of select="child/@id"/></xsl:comment>
            <xsl:element name="person">
                <xsl:attribute name="id"><xsl:value-of select="$id"/></xsl:attribute>
                <xsl:element name="name">
                    <xsl:value-of select="./child/text()"/>
                </xsl:element>
            </xsl:element>
            <xsl:element name="relation">
                <xsl:attribute name="id">
                    <xsl:value-of select="$id"/>
                </xsl:attribute>
                <xsl:element name="filename">
                    <xsl:value-of select="./image/@name"/>
                </xsl:element>
            </xsl:element>
        </xsl:for-each>
    </data>
</xsl:template>

</xsl:stylesheet>

Input XML(yours but slightly modified to make it well*formed)

<?xml version="1.0"?>
<parent>
      <child id="123456">Child Name</child>
      <image name="child.jpg"/>
</parent>

And the result

<?xml version='1.0' ?>
<data>
  <!--Child having id: 123456-->
  <person id="123456">
    <name>Child Name</name>
  </person>
  <relation id="123456">
    <filename>child.jpg</filename>
  </relation>
</data>

1 Comment

Careful - while this answer works for the OP's question, it might not be as comprehensive as the one proposed by @Dimitre Novatchev. For instance, if their were two <children>/<image> element pairs inside of a <parent> element, yours would only return the first one. Again, this isn't a scenario that the OP explicitly requested, but it's worth looking at.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.