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 December 20th, 2011, 02:21 AM
Registered User
 
Join Date: Dec 2011
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default skip creating tag based on conditions

Hi,
We are migration data from older to newer version, we are using XSLT to transform the source XML to build latest XML.
Some conditions have to be evaluated during transformation, I have listed 2 of them below:
1. Replace the old users with new users
2. SKIP building a <Folder> tag if the created date is prior to 2007.

Below is my Source XML:
Code:
<?xml version="1.0" encoding="utf-8"?>
<XML>
	<Folder id="id74" name="Folder 1">
		<Data id="id281">
			<Values value="2004-09-07" title="date_created"/>
			<Values value="sraju670" title="user_created"/>
		</Data>
	</Folder>
	<Folder id="id741" name="Folder 2">
		<Data id="id282">
			<Values value="2007-09-07" title="date_created"/>
			<Values value="sudheer" title="user_created"/>
		</Data>
	</Folder>
	<Folder id="id742" name="Folder 3">
		<Data id="id283">
			<Values value="2006-09-07" title="date_created"/>
			<Values value="raju" title="user_created"/>
		</Data>
	</Folder>
	<Folder id="id748" name="Folder 4">
		<Data id="id284">
			<Values value="2009-09-07" title="date_created"/>
			<Values value="naga" title="user_created"/>
		</Data>
	</Folder>
</XML>
In this example Folder1 & Folder3 shouldn't be exported as they are created before 2007.
The user "naga" for Folder4 is a old user (in-active), so his name has to be replaced with "admin".
I need to write a XSL which would fulfill both these conditions and build a output XML file, something like this:

OUTPUT XML:
Code:
<?xml version="1.0" encoding="utf-8"?>
<XML>
	<Folder id="id741" name="Folder 2">
		<Data id="id282">
			<Values value="2007-09-07" title="date_created"/>
			<Values value="sudheer" title="user_created"/>
		</Data>
	</Folder>
	<Folder id="id748" name="Folder 4">
		<Data id="id284">
			<Values value="2009-09-07" title="date_created"/>
			<Values value="admin" title="user_created"/>
		</Data>
	</Folder>
</XML>
Below is what I have tried so far:
1. Looping through Folder, Data, Values using <xsL:for-each>
2. Getting @title value,
A. If @title is 'date_created' then check if the date is later to 2007.
B. If @title is 'user_created' then check if user is 'naga' (or other users from another XML file) and then replace with admin.
3. Try building <Folder> tag based on date_created condition, BUT IT IS FAILING.

Below is my overall code:
Code:
<xsl:template name="rootTemplate">
	<xsl:for-each select="XML/Folder">
		<xsl:for-each select="Data">
			<xsl:for-each select="Values">
				<xsl:variable name="title" select="@title"/>
					<xsl:variable name="attribute_type" select="@title"/>
						<xsl:if test="$attribute_type = 'owning_user'">
								<xsl:message> owning_user :  <xsl:value-of select="@value" /></xsl:message>
						</xsl:if>
						<xsl:if test="$attribute_type = 'last_mod_date'">
								<xsl:variable name="last_modified_date_value" select="@value"/>
								<xsl:message>  last_mod_date : <xsl:value-of select="$last_modified_date_value" /></xsl:message>
								<xsl:variable name="last_mod_date_formatted" select="xs:integer(translate(substring($last_modified_date_value,1,10),'-',''))"/>
									<xsl:message> last_mod_date_formatted: <xsl:value-of select="$last_mod_date_formatted"/></xsl:message>
										<xsl:choose>
											<xsl:when test="$last_mod_date_formatted &gt;= 20070101">
												<xsl:message> Input Date : <xsl:value-of select="$last_mod_date_formatted"/> is greater than or equal to 20070101, so MIGRATE</xsl:message>
													<xsl:element name="Folder">
														<xsl:attribute name="id"> 
															<xsl:value-of select="@id"/>
														</xsl:attribute>
														<xsl:element name="Data">
															<xsl:attribute name="id"> 
																<xsl:value-of select="@id"/>
															</xsl:attribute> 
															<xsl:element name="Values">
																<xsl:attribute name="id"> 
																	<xsl:value-of select="@id"/>
																</xsl:attribute> 
															</xsl:element>
														</xsl:element>
													</xsl:element>
											</xsl:when>
											<xsl:otherwise>
												<xsl:message> Input Date : <xsl:value-of select="$last_mod_date_formatted"/> is less than or equal to 20070101, so SKIP </xsl:message>
											</xsl:otherwise>
										</xsl:choose>
						</xsl:if>					
			</xsl:for-each>
		</xsl:for-each>
	</xsl:for-each>
</xsl:template>

Any help is highly appreciated.
 
Old December 20th, 2011, 05:32 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Thumbs up

You've described your solution in terms of pseudo-code which is very procedural (do this, then do this), and you've also tried to code it in a very procedural way. You initial description of the problem (which gives a set of rules to be applied) is a much more useful starting point, because XSLT allows you to express the transformation as a set of rules.

Start with a default template rule that copies everything unchanged:

Code:
<xsl:template match="*">
  <xsl:copy><xsl:copy-of select="@*"/><xsl:apply-templates/></xsl:copy>
</xsl:template>
Add a rule that skips old folders:

Code:
<xsl:template match="Folder[Data/Values[@title='date_created'][xs:date(@value) lt xs:date('2007-01-01')]"/>
Add a rule that renames inactive users:

Code:
<xsl:template match="Value[@title='user-created'][@value=doc('inactive-users.xml')//user]">
  <Value title="user-created" value="admin"/>
</xsl:template>
XSLT as a rule-based language is perfect for this kind of thing - you just have to get procedural programming out of your head.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old December 20th, 2011, 06:23 AM
Registered User
 
Join Date: Dec 2011
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks Michael.
I have been programming in Java for quite long time and so I try procedurally, I have even worked in XSLT but not very extensively.

I shall try that option you have suggested.

What if I want to modify some more tags such as:
1. Remove the "ApplicationRef" tag under Folder tag.
2. Change Folder Name by Prefixing value to the name, from "Folder 1" to "XML_App_Folder 1"
3. Check the "Folder" subType and change value based on some condition, such as if it is "Windows XP" change it to "Win 32", and it is "Windows NT" change it to "Windows", or something like that, etc.

Code:
<?xml version="1.0" encoding="utf-8"?>
<XML>
	<Folder id="id74" name="Folder 1" subType="Windows XP">
                <ApplicationRef version="wkLFT7N5VR5MWB" application="XML_App"/>
		<Data id="id281">
			<Values value="2004-09-07" title="date_created"/>
			<Values value="sraju670" title="user_created"/>
		</Data>
	</Folder>
	<Folder id="id741" name="Folder 2" subType="Windows NT">
                <ApplicationRef version="wkLFT7N5VR5MWB" application="XML_App"/>
		<Data id="id282">
			<Values value="2007-09-07" title="date_created"/>
			<Values value="sudheer" title="user_created"/>
		</Data>
	</Folder>
	<Folder id="id742" name="Folder 3" subType="Windows XP">>
                <ApplicationRef version="wkLFT7N5VR5MWB" application="XML_App"/>
		<Data id="id283">
			<Values value="2006-09-07" title="date_created"/>
			<Values value="raju" title="user_created"/>
		</Data>
	</Folder>
	<Folder id="id748" name="Folder 4" subType="Windows NT">
                <ApplicationRef version="wkLFT7N5VR5MWB" application="XML_App"/>
		<Data id="id284">
			<Values value="2009-09-07" title="date_created"/>
			<Values value="naga" title="user_created"/>
		</Data>
	</Folder>
</XML>

Is there a way (even procedural) where I can build "Folder" and other tags (in my output XML) instead of using
Code:
xsl:copy
and modify values while building ???

Thanks again.
 
Old December 20th, 2011, 06:56 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You can construct an element node with any name you like using xsl:element.

You're not constructing tags, by the way. The serializer does that. When you construct an element node in the result tree, and then serialize it, the serializer will automatically output the element node using either two tags (a start and end tag) or one tag (an empty element tag) depending on whether the element is empty or not. Using "tag" to mean "element" is likely to confuse people.

If you want to make more modifications, generally you can just add more template rules. Of course you need to start considering what happens if they conflict, that is, if more than one rule applies to the same element.
__________________
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
select the group of rows based on the three XML fields and with these conditions. CCPuser XSLT 3 October 22nd, 2010 09:11 AM
select the group of rows based on the three XML fields and with conditions. CCPuser BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition ISBN: 978-0-470-19274-0 1 October 22nd, 2010 09:06 AM
Display or hide ModalPopupExtender based on client-site conditions Dmitriy ASP.NET 3.5 Professionals 5 August 20th, 2009 01:04 PM
selection based on conditions rajesh_css XSLT 3 October 2nd, 2008 08:06 PM
copying a tag to output based on a query anboss XSLT 6 July 17th, 2008 11:10 AM





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