[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

RE: [xsl] semantic xslt transformations


Subject: RE: [xsl] semantic xslt transformations
From: "McNally, David" <David.McNally@xxxxxxxxxx>
Date: Tue, 12 Aug 2003 17:00:04 -0400

I have not done this before, so thought I'd try implementing the solution
proposed by Mukul.  I used a slightly different mapping syntax, just because
I like doing string comparisons, and embedded the mapping in the stylesheet
for clarity.  

Nothing terribly complicated here - just running the document through one
moded set of templates to convert the element and attribute names to their
semantically normalized forms, then using the node-set extension function to
apply templates on the result.  I've completely ignored namespaces - not
sure if that's appropriate.  I imagine there are better implementations of
this solution, but I think this works.

Hope this helps,
David.
--
David McNally            Moody's Investors Service
Software Engineer        99 Church St, NY NY 10007 
David.McNally@xxxxxxxxxx            (212) 553-7475 


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="urn:schemas-microsoft-com:xslt" xmlns:rep="http://whatever.com"
xmlns:saxon="http://icl.com/saxon">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<rep:elementmaps>
  <!--  
    name attribute is the semantic name, the whitespace delimited content
(with whitespace at start and end
    of the content) list the input names which should be mapped to the
semantic name.
    I could make this case insensitive...but right now it is not 
  -->
  <rep:elementmap name="firstName"> fName fname firstName firstname
namefirst nameFirst </rep:elementmap>
  <rep:elementmap name="bar"> bar BAR Bar bAr baR </rep:elementmap>
  <rep:elementmap name="blah"> blah kjasd BLAH </rep:elementmap>
</rep:elementmaps>

<rep:attmaps>
  <!--
    As above, but need to specify which element the attributes appear on.  
    If set to * then applies to any element (though can be overridden)  
  -->
  <rep:attmap element="firstName" name="link"> href HREF LINK linker
</rep:attmap>
  <rep:attmap element="firstName" name="id"> id ID Id iD </rep:attmap>
  <rep:attmap element="arg" name="link"> href link HREF LINK linker
</rep:attmap>
  <rep:attmap element="bar" name="id"> ID </rep:attmap>
  <rep:attmap element="*" name="global"> GLOBAL Global globaL globalAtt
</rep:attmap>
</rep:attmaps>

<xsl:variable name="elementmaps" select="document('')//rep:elementmaps"/>
<xsl:variable name="attmaps" select="document('')//rep:attmaps"/>

<xsl:template match="/">
  <xsl:variable name="document">
    <xsl:apply-templates select="*" mode="firstrun"/>
  </xsl:variable>
  <!-- apply templates to element children, so I don't end up in this
template again -->
  <xsl:apply-templates select="ext:node-set($document)/*"/>
</xsl:template>
  
<xsl:template match="*" mode="firstrun">
  <xsl:variable name="thisname" select="name(.)"/>
  <xsl:variable name="thisele" select="."/>
  <xsl:variable name="newname">
    <xsl:choose>
      <xsl:when test="$elementmaps/rep:elementmap[contains(.,concat('
',$thisname,' '))]">
        <xsl:value-of
select="$elementmaps/rep:elementmap[contains(.,concat(' ',$thisname,'
'))]/@name"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$thisname"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:element name="{$newname}">
    <xsl:for-each select="$thisele/@*">
      <xsl:variable name="thisatt" select="name(.)"/>
      <xsl:variable name="attname">
        <xsl:choose>
          <xsl:when
test="$attmaps/rep:attmap[@element=$newname][contains(.,concat('
',$thisatt,' '))]">
            <xsl:value-of
select="$attmaps/rep:attmap[@element=$newname][contains(.,concat('
',$thisatt,' '))]/@name"/>
          </xsl:when>
          <xsl:when
test="$attmaps/rep:attmap[@element='*'][contains(.,concat(' ',$thisatt,'
'))]">
            <xsl:value-of
select="$attmaps/rep:attmap[@element='*'][contains(.,concat(' ',$thisatt,'
'))]/@name"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$thisatt"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:attribute name="{$attname}">
        <xsl:value-of select="."/>
      </xsl:attribute>
    </xsl:for-each>
    <xsl:apply-templates mode="firstrun"/>
  </xsl:element>
</xsl:template>

<!-- These are the "real" templates, that would run on the semantically
normalized result -->

<xsl:template match="*">
  <xsl:element name="{name(.)}">
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates/>
  </xsl:element>
</xsl:template>

<xsl:template match="firstName">
  <xsl:element name="{name(.)}">
    <xsl:copy-of select="@*"/>
    <xsl:attribute name="check"><xsl:text>FIRST NAME ELEMENT
PROCESSED</xsl:text></xsl:attribute>
    <xsl:apply-templates/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>


> -----Original Message-----
> From: Nathan Shaw [mailto:n8_shaw@xxxxxxxxx] 
> Sent: Tuesday, August 12, 2003 12:36 PM
> To: XSL-List@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] semantic xslt transformations
> 
> 
> Hi all,
> 
> I am working on a project where I will be receiving
> different xml documents that contain essentially the
> same content and vary only slightly in nomenclature.
> 
> For example, one document uses <firstName>, while
> another uses <fName>, while yet another uses
> <nameFirst>. They all "mean" the same thing and have
> the same data, but are expressed differently.
> 
> To avoid having to write a separate xslt
> transformation for each document, I have been looking
> into creating a map that would tie together differing
> elements and attributes in the xml documents I receive
> to my end document's elements and attributes, thus
> allowing me to only write one xslt transformation
> using the map.
> 
> Has anyone done anything like this before? I have seen
> a presentation on it by Joshua Fox, but his method
> uses middleware. I am looking for a pure xslt solution
> here.
> 
> Thanks all.
> 
> --Nathan
> 
> 
> =====
> ------------------------------------------------------------
> Nathan Shaw
> Web Applications Developer & Real Estate Investor 
http://www.iaffectProperties.com
------------------------------------------------------------

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com

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


---------------------------------------

The information contained in this e-mail message, and any attachment thereto, is confidential and may not be disclosed without our express permission.  If you are not the intended recipient or an employee or agent responsible for delivering this message to the intended recipient, you are hereby notified that you have received this message in error and that any review, dissemination, distribution or copying of this message, or any attachment thereto, in whole or in part, is strictly prohibited.  If you have received this message in error, please immediately notify us by telephone, fax or e-mail and delete the message and all of its attachments.  Thank you.

Every effort is made to keep our network free from viruses.  You should, however, review this e-mail message, as well as any attachment thereto, for viruses.  We take no responsibility and have no liability for any computer virus which may be transferred via this e-mail message.


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



Current Thread
Keywords