RE: [xsl] Generic Lookup (Element Mapping)

Subject: RE: [xsl] Generic Lookup (Element Mapping)
From: "Faroukh Fekravar" <fekravar@xxxxxxxxxxxxxxxxxx>
Date: Wed, 8 May 2002 08:46:27 -0500
Thanks Ken, That looks great.
The reason that I did not consider more than stylesheet is that I will have
more than one mapping file (most likely 3) and am not sure how complicated
will the whole thing with that and if it's at all possible. Having said that
I did not know that it has an impact on the performance.

My concern at this moment is whether XSLT is a proper approach to solve the
problem and if yes which patterns/techniques can be used to achieve that.

I try to explain my second mapping file to see whether the technique
proposed by you can handle that one too.

My second mapping file defines the inter relationships of the traget
elements.
That looks like:

Target.xml
<?xml version="1.0" encoding="UTF-8"?>
<TragetMaps>
	<TragetMap>
		<TEname>aa_1</TEname>
		<!-- That's the name of target element -->
		<SEname>aa1</SEname>
		<!-- Info for aa_1 in context of aa1> -->
		<Attribute>
			<!-- Add an attribute to aa_1, called aa_a_1 -->
			<aa_a_1 value="UNId"/>
			<!-- The value of attribute is an Unique (in whole doc) Numeric Id -->
		</Attribute>
		<Element>
			<!-- Add an element to aa_1, called aa_e_1 -->
			<aa_e_1 constant="aa_1_Type"/>
			<!-- The value of the element is a constant (aa_1_Type) -->
		</Element>
		<Element>
			<!-- Add another element to aa_1, called aa_e_2 -->
			<aa_e_2 constant="some text"/>
			<!-- The value of the element is a constant (some text) -->
		</Element>
	</TragetMap>
	<TragetMap>
		<TEname>aa_H_1</TEname>
		<!-- That's the name of target element, note it's does not appear in the
first mapping file -->
		<SEname>aa1</SEname>
		<!-- Info for aa_H_1 in context of aa1> -->
		<Attribute>
			<!-- Add an attribute to aa_H_1, called aa_H_a_1 -->
			<aa_H_a_1 value="UNId"/>
			<!-- The value of attribute is an Unique (in whole doc) Numeric Id -->
		</Attribute>
		<Element>
			<!-- Add an element to aa_H_1, called aa_H_e_1 -->
			<aa_H_e_1 Link="aa_1_Type"/>
			<!-- The value is equal the value of aa_a_1 value. Note the names
(aa_a_1) are unique in the mapping file, It's also possible to add the whole
address/path of the source to make the life easier for XSLT to get the
data.-->
		</Element>
		<Element>
			<!-- Add another element to aa_H_1, called aa_H_e_2 -->
			<aa_H_e_2 constant="some text"/>
			<!-- The value of the element is a constant (some text) -->
		</Element>
	</TragetMap>
</TragetMaps>
Some notes:
1) value, constant and link are mutually exclusive
2) A TEname can have more than one attribute.
3) Attributes have always Is as values
4) Link can be just part of an element

The output file will look like:


<project>
    <aa_1 aa_a_1="1234567">
	 <aa_e_1>aa_1_Type</aa_e_1>
	 <aa_e_2>Some Text</aa_e_2>
       <aa_11>aa11_value</aa_11>
       <aa_12>aa12_value</aa_12>
    </aa_1>
    <aa_H_1  aa_H_a_1=12345678>
	<aa_H_e_1>1234567</aa_H_e_1> <!-- same value as aa_1.aa_a_1 -->
    </aa_H_1>
    <aa_1A>
       <aa_13>aa13_value</aa_13>
    </aa_1A>
    <aa_2>
       <aa_21>aa21_value</aa_21>
    </aa_2>
    <aa_3>
       <aa_31>aa31_value</aa_31>
    </aa_3>
</project>

My last mapping file describes the "not one-to-one mappings" between the
source and target. Some of the conditional mappings and some of them require
call to hand-crafted template, espcilly for cases when we calculate
something in the source (cumulative data) and assign the value to an element
in the target.
I'm working on a simple example on that.

I really appreicate any help,
Thanks,
Faroukh

-----Original Message-----
From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
[mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx]On Behalf Of G. Ken Holman
Sent: Tuesday, May 07, 2002 10:24 AM
To: XSL-List@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Generic Lookup (Element Mapping)


At 2002-05-07 08:15 -0500, Faroukh Fekravar wrote:
>I have been trying to write a generic xslt template to map the element
names
>based on a lookup table.

Is there a reason you want to do this in one stylesheet with both the
mapping file and the data file?

>The lookup xml file has always a subset of the elements and therefore I do
>not want to hard code the element names.

Then you need a customized stylesheet based on your mappings, especially
for speed in order to do a single pass on the input data.

>The output file is a flat xml file in opposite to the input file.

This was a particularly difficult criterion to meet.

>But my main problem is how navigate through the input file in a generic
>approach.
>I'm also just a little concern about the overall performance because the
>input file might be MBs big.

For performance reasons, I recommend you write a stylesheet that, based on
your mapping, emits a single stylesheet that is then run against your
data.  This emitted stylesheet does simple matches and should meet your
performance requirements.

An example of writing a stylesheet that writes a stylesheet is in Chapter 5
of "Definitive XSLT and XPath" which happens to be the freely-downloadable
chapter made available by Prentice Hall on the Amazon site.  It is also in
Chapter 5 of our electronic book from which the paper book was derived.

A working answer to your requirements is below.

I hope this helps.

...................... Ken


t:\ftemp>type data.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<project>
         <aa1>
                 <aa11>aa11_value</aa11>
                 <aa12>aa12_value</aa12>
                 <aa13>aa13_value</aa13>
                 <aa2>
                         <aa21>aa21_value</aa21>
                         <aa22>aa22_value</aa22>
                         <aa3>
                                 <aa31>aa31_value</aa31>
                                 <aa4>
                                         <aa41>aa41_value</aa41>
                                 </aa4>
                         </aa3>
                 </aa2>
         </aa1>
</project>

t:\ftemp>type lookup.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<Maps>
         <Map>                                           <!-- combination
of SEName, SAname and TEname is unique through
the file.-->
                 <SEname>aa1</SEname>            <!--  element name in the
input file-->
                 <SAname>aa11</SAname>           <!-- element name in the
input file, it's always
the child element of SEName-->
                 <TEname>aa_1</TEname>           <!-- element name in
output-->
                 <TAname>aa_11</TAname>          <!-- element nemae in
output, it should be the
child element of TEname-->
         </Map>
         <Map>
                 <SEname>aa1</SEname>
                 <SAname>aa12</SAname>
                 <TEname>aa_1</TEname>
                 <TAname>aa_12</TAname>
         </Map>
         <Map>
                 <SEname>aa1</SEname>
                 <SAname>aa13</SAname>
                 <TEname>aa_1A</TEname>
                 <TAname>aa_13</TAname>
         </Map>
         <Map>
                 <SEname>aa2</SEname>
                 <SAname>aa21</SAname>
                 <TEname>aa_2</TEname>
                 <TAname>aa_21</TAname>
         </Map>
<!-- no mapping for aa22 -->
         <Map>
                 <SEname>aa3</SEname>
                 <SAname>aa31</SAname>
                 <TEname>aa_3</TEname>
                 <TAname>aa_31</TAname>
         </Map>
</Maps>

t:\ftemp>type faroukh.xsl
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                 xmlns:xslo="junk"
                 version="1.0">

<xsl:namespace-alias stylesheet-prefix="xslo" result-prefix="xsl"/>

<xsl:key name="parents" match="Map" use="SEname"/>
<xsl:key name="children" match="Map" use="concat(SEname,' ',TEname)"/>

<xsl:template match="/">
   <xslo:stylesheet version="1.0">
     <xslo:output indent="yes"/>
     <xslo:template match="/project"><!--preserve project element-->
       <project>
         <xslo:apply-templates/>
       </project>
     </xslo:template>
     <xslo:template match="*"/><!--throw away unmapped-->
     <xslo:template match="text()"/><!--only keep explicitly copied text-->
     <xsl:apply-templates/>
   </xslo:stylesheet>
</xsl:template>

<xsl:template match="Map">
                            <!--only put out a single template for the
parent-->
   <xsl:if test="generate-id(.)=generate-id(key('parents',SEname))">
     <xslo:template match="{SEname}">
                  <!--needs as many apply templates as unique parent
mappings-->
       <xsl:for-each select="key('parents',SEname)[generate-id(.)=
                       generate-id(key('children',concat(SEname,'
',TEname)))]">
         <xslo:element name="{TEname}">
           <xslo:apply-templates mode="mapping">
             <xsl:attribute name="select">
               <xsl:for-each select="key('children',concat(SEname,'
',TEname))">
                 <xsl:if test="position()>1">|</xsl:if>
                 <xsl:value-of select="SAname"/>
               </xsl:for-each>
             </xsl:attribute>
           </xslo:apply-templates>
         </xslo:element>
       </xsl:for-each>
       <xslo:apply-templates/>
     </xslo:template>
   </xsl:if>
   <xslo:template match="{SEname}/{SAname}" mode="mapping">
     <xslo:element name="{TAname}">
       <xslo:value-of select="."/>
     </xslo:element>
   </xslo:template>
</xsl:template>

</xsl:stylesheet>

t:\ftemp>saxon -o mapping.xsl lookup.xml faroukh.xsl

t:\ftemp>saxon -o faroukh.out data.xml mapping.xsl

t:\ftemp>type faroukh.out
<?xml version="1.0" encoding="utf-8"?>
<project>
    <aa_1>
       <aa_11>aa11_value</aa_11>
       <aa_12>aa12_value</aa_12>
    </aa_1>
    <aa_1A>
       <aa_13>aa13_value</aa_13>
    </aa_1A>
    <aa_2>
       <aa_21>aa21_value</aa_21>
    </aa_2>
    <aa_3>
       <aa_31>aa31_value</aa_31>
    </aa_3>
</project>
t:\ftemp>rem Done!


--
Upcoming: 3-days XSLT/XPath and/or 2-days XSLFO: June 17-21, 2002
-       : 3-days XML Information Modeling: July 31-August 2, 2002

G. Ken Holman                mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Crane Softwrights Ltd.         http://www.CraneSoftwrights.com/s/
Box 266, Kars, Ontario CANADA K0A-2E0 +1(613)489-0999 (Fax:-0995)
ISBN 0-13-065196-6                      Definitive XSLT and XPath
ISBN 1-894049-08-X  Practical Transformation Using XSLT and XPath
ISBN 1-894049-07-1               Practical Formatting Using XSLFO
XSL/XML/DSSSL/SGML/OmniMark services, books(electronic, printed),
articles, training(instructor-live,Internet-live,web/CD,licensed)
Next public training:               2002-05-06,07,09,10,13,15,20,
-                    06-04,07,10,11,13,14,17,20,07-31,08-05,27,30


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread