• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

XML Tranformation using XSLT

 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi XML Gurus,
Need some help on XML tranformation using XSLT. I need help on coding the XSL for the requirement.I have a requirement where there are around 10 XML files where one has to Update,Delete, and insert elements in the XML document keeping the other nodes and information intact. So the input is an XML file, XSLT is used to process the document where it will update, delete, insert a elements and output is an XML document similiar to the input XML with slight changes in the elements.
I have read few documents and experimented a bit...
For copying we have code..
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="title">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
OR
<xsl:template match="title">
<xsl:copy-of select="*"/>
</xsl:template>
For Deleting:
<xsl:template match="nickname">
</xsl:template>
<xsl:template match="project[@status='canceled']">
</xsl:template>
For Updating :
<xsl:template match="article">
<html>
<xsl:apply-templates/>
</html>
</xsl:template>
If anyone has better ideas.Please let me know..
Thanks for the help in advance.
Regards
Swarup

------------------
 
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
1. Copying: the second template looks correct. With the first template you may have problems: if you do not provide any template to work with children of the "title" element, XSLT processor will use built-in templates, that copy the content and leave out children enclosing tags and attributes. So for the folowing xml
<root>
<element1 id="1">content1
<element2>content2</element2>
</element1>
<element3>content3</element3>
</root>

and XSLT:
<xsl:template match="element1">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

the output will be
<element1>content1
content2
</element1>
content3

which is probably not what you want. Template2, which uses <xsl:copy-of>, is correct, it will output <title> elements "as is", with all children and all attributes.
2. Templates for deleting are correct. Only small comment: you can shorten
<xsl:template match="nickname">
</xsl:template>

as:
<xsl:template match="nickname"/>
3. Updating
Here I did not quite uderstand what kind of updating you want to achieve. How your template is written, you will get the content of the "article" element and all its children wrapped in <html> tag. Is that what you want?
[This message has been edited by Mapraputa Is (edited August 04, 2001).]
 
Swarup Sathe
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
Thanks a lot for your reply. But can you please give me an example where there are lots of elements and nodes in the XML. How should the "copy-of select" statement work in that case.
<xsl:template match="title">
<xsl:copy-of select="*"/>
</xsl:template>

<root>
<element1 id="1">content1
<element2>content2</element2>
</element1>
<element3>content3</element3>
</root>
<xsl:template match="element1">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
The example you gave was for a small XML consider an example like this one..
<root>
<element1 id="1">content1
<element2>content2</element2>
</element1>
<element2 id="2">content2
<element2>content2</element2>
</element2>
<element3 id="3">content3
<element3>content3</element3>
</element3>
<element4 id="4">content4
<element4>content4</element4>
</element4>
<element5 id="5">content5
<element5>content5</element5>
</element5>
<element6>content6</element6>
</root>
how would u write the XSLT .....
3. Updating..
Updating a tag will be on the same lines as delete and add. So i will delete a particular element and then insert same element with different value.. Consider the following..
<element6>content6</element6>
Now I want to update the value with comtentx
I will delete the whole tag and insert a tag <element6>contentx</element6>
So what will be the XSLT code for it considering the above big XML.

My output will be again XML ONLY.
Thanks
Swarup

------------------
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I combined answers to both your questions in the same XSLT. If you have too many elements and (or) do not want to deal with each of them separately, you can write generic XPath to match all of them: match="root/node()" Now if you want to do something special with one of elements, "element6" in your case, you add another template with more sprecific match: match="root/element6" When XSLT processor walks through an XML document, it chooses the most specific template to apply. So all elements except "element6" will be processed by "generic" template, i.e. outputted "as is", and "element6" will be processed by dedicated template. Now, if you want to change elements' content, you can simply write it in XSLT:
<element6>contentx</element6>
and if you do not use <xsl:copy-of>, this new element will "override" the old.
The whole stylesheet will be:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<root><xsl:apply-templates/></root>
</xsl:template>
<xsl:template match="root/node()">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="root/element6">
<element6>contentx</element6>
</xsl:template>
</xsl:stylesheet>

when it is run against your big XML, the output is:
<root>
<element1 id="1">content1
<element2>content2</element2>
</element1>
<element2 id="2">content2
<element2>content2</element2>
</element2>
<element3 id="3">content3
<element3>content3</element3>
</element3>
<element4 id="4">content4
<element4>content4</element4>
</element4>
<element5 id="5">content5
<element5>content5</element5>
</element5>
<element6>contentx</element6>
</root>

 
Swarup Sathe
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
Thanks for the reply. I tried the example but it did not work..
XML file:
<?xml version="1.0"?>
<PERIODIC_TABLE>
<ATOM STATE="GAS">
<NAME>Hydrogen</NAME>
<SYMBOL>H</SYMBOL>
<ATOMIC_NUMBER>1</ATOMIC_NUMBER>
<ATOMIC_WEIGHT>1.00794</ATOMIC_WEIGHT>
<BOILING_POINT UNITS="Kelvin">20.28</BOILING_POINT>
<MELTING_POINT UNITS="Kelvin">13.81</MELTING_POINT>
<DENSITY UNITS="grams/cubic centimeter">
<!-- At 300K, 1 atm -->
0.0000899
</DENSITY>
</ATOM>
<ATOM STATE="GAS">
<NAME>Helium</NAME>
<SYMBOL>He</SYMBOL>
<ATOMIC_NUMBER>2</ATOMIC_NUMBER>
<ATOMIC_WEIGHT>4.0026</ATOMIC_WEIGHT>
<BOILING_POINT UNITS="Kelvin">4.216</BOILING_POINT>
<MELTING_POINT UNITS="Kelvin">0.95</MELTING_POINT>
<DENSITY UNITS="grams/cubic centimeter"><!-- At 300K -->
0.0001785
</DENSITY>
</ATOM>
<ATOM STATE="GAS">
<NAME>Swarup</NAME>
<SYMBOL>Sw</SYMBOL>
<ATOMIC_NUMBER>7</ATOMIC_NUMBER>
<ATOMIC_WEIGHT>7.0026</ATOMIC_WEIGHT>
<BOILING_POINT UNITS="Kelvin">7.216</BOILING_POINT>
<DENSITY UNITS="grams/cubic centimeter"><!-- At 300K -->
7.0001785
</DENSITY>
</ATOM>
</PERIODIC_TABLE>
XSL File:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl utput method="xml" indent="yes"/>

<xsl:template match="/">
<PERIODIC_TABLE><xsl:apply-templates/></PERIODIC_TABLE>
</xsl:template>
<xsl:template match="PERIODIC_TABLE/node()">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="PERIODIC_TABLE/ATOM/MELTING_POINT">
<ATOM>contentx</ATOM>
</xsl:template>
</xsl:stylesheet>
Output XML File:
<?xml version="1.0" encoding="UTF-8"?>
<PERIODIC_TABLE>
<ATOM STATE="GAS">
<NAME>Hydrogen</NAME>
<SYMBOL>H</SYMBOL>
<ATOMIC_NUMBER>1</ATOMIC_NUMBER>
<ATOMIC_WEIGHT>1.00794</ATOMIC_WEIGHT>
<BOILING_POINT UNITS="Kelvin">20.28</BOILING_POINT>
<MELTING_POINT UNITS="Kelvin">13.81</MELTING_POINT>
<DENSITY UNITS="grams/cubic centimeter">
<!-- At 300K, 1 atm -->
0.0000899
</DENSITY>
</ATOM>
<ATOM STATE="GAS">
<NAME>Helium</NAME>
<SYMBOL>He</SYMBOL>
<ATOMIC_NUMBER>2</ATOMIC_NUMBER>
<ATOMIC_WEIGHT>4.0026</ATOMIC_WEIGHT>
<BOILING_POINT UNITS="Kelvin">4.216</BOILING_POINT>
<MELTING_POINT UNITS="Kelvin">0.95</MELTING_POINT>
<DENSITY UNITS="grams/cubic centimeter">
<!-- At 300K -->
0.0001785
</DENSITY>
</ATOM>
<ATOM STATE="GAS">
<NAME>Swarup</NAME>
<SYMBOL>Sw</SYMBOL>
<ATOMIC_NUMBER>7</ATOMIC_NUMBER>
<ATOMIC_WEIGHT>7.0026</ATOMIC_WEIGHT>
<BOILING_POINT UNITS="Kelvin">7.216</BOILING_POINT>
<DENSITY UNITS="grams/cubic centimeter">
<!-- At 300K -->
7.0001785
</DENSITY>
</ATOM>
</PERIODIC_TABLE>

Here I want to remove the element which does not have the MELTING-POINT Tag in it.
Thanks..
------------------
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey, it did work on your previous data!
Regarding your new data: if you want to remove the element which does not have the MELTING-POINT tag in it, you probably should not use MELTING-POINT in your match expression, because such expression will match the opposite condition. Use match="PERIODIC_TABLE/ATOM[not(MELTING_POINT)]" instead.
if you want to delete such elements, your template will look like
<xsl:template match="PERIODIC_TABLE/ATOM[not(MELTING_POINT)]"/>
 
Swarup Sathe
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
I found out a better solution based on your input..
The XSL is as follows :
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl utput method="xml" indent="yes"/>

<xsl:template match="/">
<PERIODIC_TABLE><xsl:apply-templates/></PERIODIC_TABLE>
</xsl:template>
<xsl:template match="PERIODIC_TABLE/node()">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="PERIODIC_TABLE/ATOM[not(MELTING_POINT)]">
<xsl:element name="ATOM">
<xsl:copy-of select="@*"/>
<xsl:copy-of select="node()"/>

<xsl:element name="MELTING_POINT">
<xsl:attribute name="UNITS">Kelvin</xsl:attribute>0.00</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Tell me what do you think about it.
Thanks
Swarup
 
reply
    Bookmark Topic Watch Topic
  • New Topic