xsl-list
[Top] [All Lists]

RE: semantic xslt transformations

2003-08-12 14:00:04
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(_dot_)McNally(_at_)Moodys(_dot_)com            (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[(_at_)element=$newname][contains(.,concat('
',$thisatt,' '))]">
            <xsl:value-of
select="$attmaps/rep:attmap[(_at_)element=$newname][contains(.,concat('
',$thisatt,' '))]/@name"/>
          </xsl:when>
          <xsl:when
test="$attmaps/rep:attmap[(_at_)element='*'][contains(.,concat(' ',$thisatt,'
'))]">
            <xsl:value-of
select="$attmaps/rep:attmap[(_at_)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(_at_)yahoo(_dot_)com] 
Sent: Tuesday, August 12, 2003 12:36 PM
To: XSL-List(_at_)lists(_dot_)mulberrytech(_dot_)com
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



<Prev in Thread] Current Thread [Next in Thread>