Change the value of an attribute according to the value of another attribute

Change the value of an attribute according to the value of another attribute

Post by patrizio.t » Wed, 23 Aug 2006 21:57:05


Hi All,

I'would like to write an XSL transformation that changes the value of
the atribute of a given element according to the value of another
atttribute of the same element.

For instance, given the following XML file:

<?xml version="1.0" encoding="UTF-8"?>
<sample xmlns:xsi=" http://www.yqcomputer.com/ "
xsi:noNameSpaceSchemaLocation="sample.xsd">
<parent-element>
<child-element name="AAA" value="XXX"/>
<child-element name="BBB" value="XXX"/>
</parent-element>
</sample>

I would obtain the following one:

<?xml version="1.0" encoding="UTF-8"?>
<sample xmlns:xsi=" http://www.yqcomputer.com/ "
xsi:noNameSpaceSchemaLocation="sample.xsd">
<parent-element>
<child-element name="AAA" value="AAA_VALUE"/>
<child-element name="BBB" value="BBB_VALUE"/>
</parent-element>
</sample>

where the value of the 'value' attribute of the first child-element has
been changed to AAA_VALUE because the value of the 'name' attribute was
AAA; the value of the 'value' attribute of the second child-element has
been changed to BBB_VALUE because the value of the 'name' attribute was
AAA.

I wrote the following XSLT to do the job:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl=" http://www.yqcomputer.com/ "
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child-element[@name='AAA']">
<xsl:apply-templates select="@*[local-name() != 'value']" />
<xsl:attribute name="value">
<xsl:text>AAA_VALUE</xsl:text>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>

but it only handles the first child-element; I don't know how to handle
both the child-element, and possibly more then two, in a single
transform, is it possible? or maybe I need to chain multiple
transformations?

Thanks a lot for your help

Patrizio
 
 
 

Change the value of an attribute according to the value of another attribute

Post by toudide » Wed, 23 Aug 2006 22:06:29

i don't understand what you want as the output of the transformation. get
some example of xml document and output xml document

td

 
 
 

Change the value of an attribute according to the value of another attribute

Post by Martin Hon » Wed, 23 Aug 2006 22:09:30


You could simply use the first template you have plus
<xsl:template match="child-element/@value">
<xsl:attribute name="{name()}"><xsl:value-of
select="concat(../@name, '_VALUE')"/></xsl:attribute>
</xsl:template>


--

Martin Honnen
http://www.yqcomputer.com/
 
 
 

Change the value of an attribute according to the value of another attribute

Post by patrizio.t » Wed, 23 Aug 2006 22:34:57


Thanks a lot for your suggestion, but maybe the sample XML was not
very self-explaining, may fault.
What I would obtain is indeed to transformt an XML like this:

<?xml version="1.0" encoding="UTF-8"?>
<sample xmlns:xsi=" http://www.yqcomputer.com/ "
xsi:noNameSpaceSchemaLocation="sample.xsd">
<parent-element>
<child-element name="AAA" value="anOldValueForAAA"/>
<child-element name="BBB" value="anOldValueForBBB"/>
<child-element name="CCC" value="anOldValueForCCC"/>
...
</parent-element>
</sample>

Into another XML like the follwoing:

<?xml version="1.0" encoding="UTF-8"?>
<sample xmlns:xsi=" http://www.yqcomputer.com/ "
xsi:noNameSpaceSchemaLocation="sample.xsd">
<parent-element>
<child-element name="AAA" value="aNewValue1"/>
<child-element name="BBB" value="aNewValue2"/>
<child-element name="CCC" value="aNewValue3"/>
...
</parent-element>
</sample>

whose content has been determined according to the following rules:

FOR EACH child-element
IF name == AAA THEN value = aNewValue1
ESLE IF name == BBB THEN value = aNewValue2
ESLE IF name == CCC THEN value = aNewValue3
...

Thanks again for your help

Regards,

Patrizio
 
 
 

Change the value of an attribute according to the value of another attribute

Post by Martin Hon » Wed, 23 Aug 2006 22:40:59


I see no way then but hardcoding the different cases e.g.
<xsl:template match="child-element[@name = 'AAA']/@value">
<xsl:attribute name="{name()}">aNewValue1</xsl:attribute>
<xsl:template>

<xsl:template match="child-element[@name = 'BBB']/@value">
<xsl:attribute name="{name()}">aNewValue2</xsl:attribute>
<xsl:template>

<xsl:template match="child-element[@name = 'CCC']/@value">
<xsl:attribute name="{name()}">aNewValue3</xsl:attribute>
<xsl:template>
(plus the identity transformation template, the first one you already had).

--

Martin Honnen
http://www.yqcomputer.com/
 
 
 

Change the value of an attribute according to the value of another attribute

Post by Philippe P » Wed, 23 Aug 2006 23:04:52


here is a better strategy : a kind of associative array

<data:values>
<val name="AAA">aNewValue1</val>
<val name="BBB">aNewValue2</val>
<val name="CCC">aNewValue3</val>
</data:values>
<xsl:template match="child-element/@value">
<xsl:attribute name="{name()}">
<xsl:value-of
select="document()/*/data:values/val[@name=current()/../@name]"/>
</xsl:attribute>
<xsl:template>

I did it quickly, I hope that there is an "apply template" on the
attribute, otherwise those defined above won't be invoked

Don't miss the namespace declaration for the prefix "data" : XSLT
requires a prefix name at this place of the stylesheet

--
Cordialement,

///
(. .)
--------ooO--(_)--Ooo--------
| Philippe Poulard |
-----------------------------
http://www.yqcomputer.com/
Have the RefleX !
 
 
 

Change the value of an attribute according to the value of another attribute

Post by richar » Wed, 23 Aug 2006 23:16:26

In article <44eb096f$0$10167$ XXXX@XXXXX.COM >,



You could use a table. To do this you could use a couple of less
commonly used features of XSLT:

- you can put any elements in a stylesheet provided that they
are in some namespace other than the XSLT namespace;
- you can refer to the stylesheet itself in a call to the document
function by using the same-document URI "".

So you could put elements like this at the top-level of the stylesheet:

<x:new name="AAA" value="aNewValue1"/>
<x:new name="BBB" value="aNewValue2"/>
...

(you'll have to declare the prefix "x" of course, with some namespace
name of your own choosing).

Then you can look up values in this table by using the document function:

<xsl:template match="child-element/@value">
<xsl:copy-of select="document('')//x:new[@name=current()/../@name]/@value"/>
</xsl:template>

-- Richard
 
 
 

Change the value of an attribute according to the value of another attribute

Post by Martin Hon » Wed, 23 Aug 2006 23:27:42


Yes, Philippe has already suggested the same approach. Nevertheless you
have to hardcode the different cases in the stylesheet as there seemed
to be no way to infer the new value from the old one.


--

Martin Honnen
http://www.yqcomputer.com/
 
 
 

Change the value of an attribute according to the value of another attribute

Post by patrizio.t » Wed, 23 Aug 2006 23:53:11


Thanks a lot to everyone!

the hard-coded solution works fine and is enough for what I need at
this time; also the associative table solution is very valuable and
I'll add it to my toolbox for the future... when I'll be more
proficient with XSLT ;-)

I've only another quick question

Is it possible to remove one or more elements according to the value of
an element's attribute; i.e. given the following source XML file:

<?xml version="1.0" encoding="UTF-8"?>
<sample xmlns:xsi=" http://www.yqcomputer.com/ "
xsi:noNameSpaceSchemaLocation="sample.xsd">
<parent-element>
<child-element name="AAA" value="XXX"/>
<child-element name="BBB" value="XXX"/>
<child-element name="CCC" value="XXX"/>
<additional-data type="text"/>
<additional-info type="text"/>
</parent-element>
</sample>

is it possible, changing somewhat the last leg to the above IF - ELSE
IF switch:

...
ELESE IF name = 'CCC' THEN {
value = aNewValue3
remove elements additional-data and additional-info type
}

to obtain the following result:

<?xml version="1.0" encoding="UTF-8"?>
<sample xmlns:xsi=" http://www.yqcomputer.com/ "
xsi:noNameSpaceSchemaLocation="sample.xsd">
<parent-element>
<child-element name="AAA" value="aNewValue1"/>
<child-element name="BBB" value="aNewValue2"/>
<child-element name="CCC" value="aNewValue3"/>
</parent-element>
</sample>

Thanks again for all your support

Regards,

Patrizio