Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old August 16th, 2010, 07:40 PM
Authorized User
 
Join Date: Jul 2010
Posts: 27
Thanks: 6
Thanked 0 Times in 0 Posts
Default Tranform to expect xml file

My source document:
Code:
<?xml version="1.0" encoding="UTF-8" ?> 
<tourcompany id="CMP001" name= "pacific cmp">
<country id="FRA" name="France">
<citylist id="list001" name="CityofFRA">
<city id="CT001" name="Paris">
  <destination>PD1</destination> 
  <destination>PD2</destination> 
  <destination>PD3</destination> 
  <destination>PD4</destination> 
  </city>
<city id="CT002" name="Versailles">
  <destination>VD1</destination> 
  <destination>VD2</destination> 
  <destination>VD3</destination> 
  <destination>VD4</destination> 
  <destination>VD5</destination> 
    </city>
  </citylist>
  <zoo id="PD1" name="BurgerZoo" /> 
  <park id="PD2" name="partABC" /> 
  <church id="PD3" name="AtoZchurch" /> 
  <museum id="PD4" name="VANGT">
  <artmuseum/>
  </museum> 
<direction_path id="PH123">
  <from>PD1</from> 
  <to>PD3</to> 
  </direction_path>
  <direction_path id="PH124">
  <from>PD3</from> 
  <to>PD2</to> 
  </direction_path>
  <direction_path id="PH125">
  <from>PD2</from> 
  <to>PD4</to> 
  </direction_path>
    
<zoo id="VD1" name="GDF">
  <bigzoo /> 
</zoo>
<part id="VD2" name="KALA">
  <nationalpart/> 
 </part>
  <part id="VD3" name="Disneyalnd">
  <waterpart/> 
  </part>
<church id="VD4" name="SANT">
<museum id="VD5" name="alibaba">
  <historymuseum/>
  </museum>
  
  <direction_path id="PH001" >
  <from>VD1</from> 
  <to>VD2</to> 
  </direction_path>
  <direction_path id="PH002">
  <from>VD2</from> 
  <to>VD3</to> 
  </direction_path>
  <direction_path id="PH003">
  <from>VD3</from> 
  <to>VD5</to> 
  </direction_path>
  <direction_path id="PH004">
  <from>VD5</from> 
  <to>VD4</to> 
  </direction_path>
 </country>  
 </tourcompany>
I wanna transform to expected document:
Code:
<org id='COUNTRY'  class = "COUNTRY">
   <org id="list001" class ="CITYLIST">
	  <org><text><fill>CityofFRA</fill></text></org>
		<org id="CT001" class ="CITY" countryID="FRA">
		    <org><text><fill>Paris</fill></text></org>
		    <org id="PD1" class="ZOO" CityID="CT001">
		         <text>BurgerZoo</text>
		    </org>
	            <org id="PD2" class="PART" CityID="CT001">
			 <text>partABC</text>
		    </org>
		    <org id="PD3" class="CHURCH" CityID="CT001">
			 <text>AtoZchurch</text>
		    </org>
		    <org id="PD4" class="ARTMUSEUM" CityID="CT001">
			 <text>VANGT</text>
		      </org>
		      <org id="DIRECTION_PATH_CT001" class="DIRECTION_PATH">
			 <org id="PH123" class="CONNECTION" source="PD1" target="PD3"/>  
			  <org id="PH124" class="CONNECTION" source="PD3" target="PD2"/>  
			  <org id="PH125" class="CONNECTION" source="PD2" target="PD4"/>  
			</org>			 
		 </org>	 
		 <org id="CT002" class ="CITY" countryID="FRA">
			<org><text><fill>Versailles</fill></text></org>
			 <org id="VD1" class="ZOO" CityID="CT002">
			    <text>GDF</text>
			 </org>
			 <org id="VD2" class="NATIONALPART" CityID="CT002">
			    <text>KALA</text>
			 </org>
			 <org id="VD3" class="WATERPART" CityID="CT002">
			     <text>Disneyalnd</text>
			 </org>
			 <org id="VD4" class="CHURCH" CityID="CT002">
			    <text>SANT</text>
			 </org>
			 <org id="VD5" class="HISTORYMUSEUM" CityID="CT002">
				 <text>alibaba</text>
			 </org>
			 <org id="DIRECTION_PATH_CT001" class="DIRECTION_PATH">
			   <org id="PH001" class="CONNECTION" source="VD1" target="VD2"/>  
			   <org id="PH002" class="CONNECTION" source="VD2" target="VD3"/>  
			   <org id="PH003" class="CONNECTION" source="VD3" target="VD5"/>  
  			   <org id="PH004" class="CONNECTION" source="VD5" target="VD4"/>  
			 </org>			 
		</org>	 
	 </org> 
 </org>
Please, give me the suggestion for this transformation.

Last edited by metinhoclam; August 16th, 2010 at 07:44 PM..
 
Old August 16th, 2010, 07:53 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Define a key:

Code:
<xsl:key name="id" match="*[@id]" use="@id"/>
and then write template rules along these lines:

Code:
<xsl:template match="destination">
  <xsl:apply-templates select="key('id', .)"/>
</xsl:template>
which has the effect that when you find a destination PD1, you invoke the template rule for the <zoo id="PD1"> element.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
The Following User Says Thank You to mhkay For This Useful Post:
metinhoclam (August 17th, 2010)
 
Old August 17th, 2010, 01:34 AM
Authorized User
 
Join Date: Jul 2010
Posts: 27
Thanks: 6
Thanked 0 Times in 0 Posts
Default There are a lot of rule

Three main rules for this transform but I cannot imagine the way to transform:
1. All element that has 'destination id' inside city will become the element childs inside that "CITY" class.

2. The @name become text element: only "CITY" and "CITYLIST" get 1 one more layer '<org><text><fill>@name</fill></text></org>'. For the remaining elements can be put directly: '<text>@name</text>'

3. If there are the other child inside the element, it will become the new element. For example: for the "museum" if it has element "artmuseum" then class name become "ARTMUSEUM" . Instead of "MUSEUM"

The problem is how to check whether the element contains any element or not to invoke the corresponding template. Because these child elements will become new class, not its parent.

The suggestion that use key <xsl:key name="id" match="*[@id]" use="@id"/> is new for me. I will try this way and post the transformation ASAP. Thanks

Last edited by metinhoclam; August 17th, 2010 at 01:48 AM..
 
Old August 17th, 2010, 04:01 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Thanks for the supplementary information. It's much easier to offer help if you say why you're finding the problem difficult, rather than just offering a blank sheet of paper.

My suggestion in my previous answer addresses your first question. The template rule for <destination> uses the key() function to locate the element with the corresponding ID value, in this case a <zoo> element, and applies templates to it; if you have a template for <zoo> elements like this:

Code:
<xsl:template match="zoo">
  <org id="{@id}" class="ZOO">
     <text><xsl:value-of select="@name"/></text>
  </org>
</xsl:template>
then you are most of the way there. The only thing this doesn't do is to generate the CityID attribute. To achieve that you need to add an <xsl:with-param name="cityID" select="../@id"/> parameter as a child of the apply-templates element, and then add <xsl:param name="cityID"/> to the zoo template, enabling you to output the attribute as CityID="{$cityID}".

The next stage is to generalize this. It seems that you want to treat zoo, museum, artmuseum etc in the same way. You can handle this with a generic template like this:

Code:
<xsl:template match="zoo|museum|artmuseum">
  <xsl:param name="cityID"/>
  <org id="{@id}" class="{upper-case(name())}" CityID="{$cityID}">
     <text><xsl:value-of select="@name"/></text>
  </org>
</xsl:template>
The function upper-case() is XSLT 2.0 only. If you're using 1.0 you need to write translate(name(), 'abcde...', 'ABCDE...').
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old August 17th, 2010, 10:10 AM
Authorized User
 
Join Date: Jul 2010
Posts: 27
Thanks: 6
Thanked 0 Times in 0 Posts
Default My transformation file...but it doesn't work... could you show me where is the prob?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="id" match="*[@id]" use="@id"/>
<xsl:template match="tourcompany">
<xsl:apply-templates />
</xsl:template>

<xsl:template match="country">
<org class ="COUNTRY" id="COUNTRY">
<text><xsl:value-of select="@name"/></text>
<xsl:apply-templates select="citylist"/>
</org>
</xsl:template>
<xsl:template match="citylist">
<org class ="CITYLIST" id="{@id}">
<org><text><xsl:value-of select="@name"/></text></org>

<xsl:apply-templates select="city"/>
</org>
</xsl:template>
<xsl:template match="city">
<org class ="CITY" id="{@id}">
<org><text><xsl:value-of select="@name"/></text></org>

<xsl:apply-templates select="*"/>
</org>
</xsl:template>

<xsl:template match="destination">
<xsl:apply-templates select="key('id',.)">
<xsl:with-param name="CityID" select="../@id"/>
</xsl:apply-templates>
</xsl:template>

<xsl:template match="*">
<xsl:param name="CityID"/>
<org id="{@id}" class="{upper-case(name())}" CityID="{$CityID}">
<text><xsl:value-of select="@name"/></text>
</org>
</xsl:template>

</xsl:stylesheet>

Last edited by metinhoclam; August 20th, 2010 at 06:49 PM..
 
Old August 17th, 2010, 10:29 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

It's not working because it's full of garbage.

Why do you have a rule to ignore every destination except the first? There was nothing like that in your requirements.

In your template rule for match="country", why do you have this: <xsl:apply-templates select="key('id', .)"/>? "." selects the string value of the country, but the country contains lots of element content, so this is meaningless.

Why are you doing this: <xsl:if test="../../../zoo[@id = current()/../*]" > <xsl:apply-templates select="zoo"/></xsl:if>? I told you how to get from the destination to the zoo element, and you've used that code, so this is totally unnecessary, as well as being useless, because the destination does not have a zoo child, so the apply-templates will do nothing whether the test succeeds or not.

The next instruction <xsl:apply-templates select="../../../*/from = current()/../* or ../../../*/to = current()/../*" mode="path"/ is even more mind-boggling, I simply have no idea what you were thinking when you wrote this.

It looks to me as if you've got a lot of learning to do. Please, before you come back to this thread, read some books and tutorials, read some example code of gradually increasing complexity, and generally take the trouble to understand the way the language works. You've parachuted into China and you're asking the nearest Chinaman to teach you how to speak Chinese - that's not an efficient strategy.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
Tranform to expect xml file metinhoclam XSLT 2 July 28th, 2010 01:01 PM
Tranform to expect xml file metinhoclam XSLT 0 July 27th, 2010 06:37 PM
Split xml file with result document and javax.xml.transform.Transformer. nisargmca XSLT 3 January 12th, 2010 06:26 AM
Using XSLT to tranform XML into JSF pdimilla XSLT 4 July 3rd, 2009 03:50 AM
get error while tranform blank xml pradipkumar XSLT 4 November 20th, 2007 01:42 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.