XML.orgXML.org
FOCUS AREAS |XML-DEV |XML.org DAILY NEWSLINK |REGISTRY |RESOURCES |ABOUT
OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]
Re: [xml-dev] RE: Declarative programming requires a different mindset

Hi,

I learned from a colleague that changing namespaces is preferably
done by a modified copy stylesheet (no need to use "document()").
Find below a sample for just changing the default namespace (no prefix):

$ cat change.xsl
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

  <xsl:output method="xml" />

  <xsl:template
    match="*[namespace-uri()='http://www.example.com/v30']">
    <xsl:element name="{name()}"
      namespace="http://www.example.com/v31";>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

$ cat data.xml
<profileRequest xmlns="http://www.example.com/v30";>
  <profileID>1234567</profileID>
  <aSequence>1</aSequence>
  <timeStamp>2010-03-22T09:13:45Z</timeStamp>
</profileRequest>

$ java -jar saxon9he.jar -xsl:change.xsl -s:data.xml -versionmsg:off ; echo
<?xml version="1.0" encoding="UTF-8"?><profileRequest
xmlns="http://www.example.com/v31";>
  <profileID>1234567</profileID>
  <aSequence>1</aSequence>
  <timeStamp>2010-03-22T09:13:45Z</timeStamp>
</profileRequest>
$


Mit besten Gruessen / Best wishes,

Hermann Stamm-Wilbrandt
Developer, XML Compiler, L3
WebSphere DataPower SOA Appliances
----------------------------------------------------------------------
IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Martin Jetter
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294


                                                                           
             "Costello, Roger                                              
             L."                                                           
             <costello@mitre.o                                          To 
             rg>                       "xml-dev@lists.xml.org"             
                                       <xml-dev@lists.xml.org>             
             03/20/2010 05:35                                           cc 
             PM                                                            
                                                                   Subject 
                                       [xml-dev] RE: Declarative           
                                       programming requires a different    
                                       mindset                             
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           




Hi Folks,

The imperative mindset dies hard.

Yesterday I wrote an XSLT transform. I was very proud of it. This morning I
realized that I had written it imperatively. Oops!

I re-wrote it, in a declarative fashion. I'd like to share with you the
imperative version and then the declarative version.

Perhaps you've had a similar experience? Would you show how you started
with an imperative implementation and then re-worked it into a declarative
implementation?


Problem: create an XSLT transform that changes an XML document's namespaces
and prefixes.

Example: Suppose an XML document uses these namespaces:
    - http://www.secret-domain.org
    - http://www.temperature.org

And it uses these namespace prefixes:
    - Secret
    - Temp

My XSLT transform maps each namespace to a new namespace, e.g.,

Change:
    - http://www.secret-domain.org
to:
    - http://www.namespaces.org/NS1/

My XSLT also creates a new namespace prefix, e.g., change the prefix,
Secret, to the prefix, NS1.

Here's a sample XML document:

<Secret:Weather xmlns:Secret="http://www.secret-domain.org";>
    <Secret:Location>Atlantistan</Secret:Location>
    <Secret:Date>2009-09-30T12:26:00</Secret:Date>
    <Temp:Temperature xmlns:Temp="http://www.temperature.org";>
        91
    </Temp:Temperature>
</Secret:Weather>


Here's the output of my XSLT transform:

<NS1:Weather xmlns:NS1="http://www.namespaces.org/NS1/";>
    <NS1:Location>Atlantistan</NS1:Location>
    <NS1:Date>2009-09-30T12:26:00</NS1:Date>
    <NS2:Temperature xmlns:NS2="http://www.namespaces.org/NS2/";>
        91
    </NS2:Temperature>
</NS1:Weather>

Notice that the namespaces and prefixes have been changed.

I used XSLT 1.0 to implement this.


VERSION #1 (IMPERATIVE MINDSET)

I created two string variables, one to hold the namespaces of the input XML
document and a second variable to hold the namespaces of the output XML
document (and I prefixed the latter namespaces):

<xsl:variable name="input-document-namespaces"
              select="'http://www.secret-domain.org
                       http://www.temperature.org'"/>

<xsl:variable name="use-these-namespaces"
              select="'NS1:http://www.namespaces.org/NS1/
                       NS2:http://www.namespaces.org/NS2/'"/>

I wrote an XSLT named template to walk down the two string variables in
parallel. My "list walking" code is at the end of this message.

"Walk down two lists" ... that's an imperative mindset. Oops!


VERSION #2 (DECLARATIVE MINDSET)

This morning I remembered a fabulous technique that I learned from Dimitre
Novatchev.

Rather than creating string variables, create some XML and insert it
directly into the XSLT transform document:

<f:namespace-mappings>
    <f:namespace-map>
        <f:input-document>
            <f:namespace>
                http://www.secret-domain.org
            </f:namespace>
        </f:input-document>
        <f:output-document>
            <f:namespace>
                http://www.namespaces.org/NS1/
            </f:namespace>
            <f:prefix>
                NS1
            </f:prefix>
        </f:output-document>
    </f:namespace-map>
    <f:namespace-map>
        <f:input-document>
            <f:namespace>
                http://www.temperature.org
            </f:namespace>
        </f:input-document>
        <f:output-document>
            <f:namespace>
                http://www.namespaces.org/NS2/
            </f:namespace>
            <f:prefix>
                NS2
            </f:prefix>
        </f:output-document>
    </f:namespace-map>
</f:namespace-mappings>

Note: the XML must be in a namespace other than the XSL namespace. I placed
this namespace declaration at the top of my XSLT document:

    xmlns:f="f:8B9C63F4-F4AB5D11-994A0001-B4CD626F"

The XML contains a <namespace-map> element for each input namespace. It
maps an input namespace to the desired output namespace and to a prefix.
For example, it maps this input namespace:

    http://www.secret-domain.org

to this output namespace:

    http://www.namespaces.org/NS1/

and to this prefix:

    NS1:


Suppose the value of a variable, $ns, is an input namespace (such as
http://www.secret-domain.org). The output namespace and prefix is obtained
simply by looking them up in the XML:

<xsl:variable name="namespace-map"
     select="document('')/*//f:namespace-map
         [f:input-document/f:namespace=$ns]" />

<xsl:variable name="use-this-namespace"
      select="$namespace-map/f:output-document/f:namespace" />

<xsl:variable name="use-this-prefix"
      select="$namespace-map/f:output-document/f:prefix" />

Recap: the mappings are in XML. Select the desired values simply by
navigating the XML.

That's declarative. That's ultra cool.

I am very pleased with my new, declarative, XSLT transform. It is:

1.           Shorter than the imperative version.
2.           Much easier to understand.

/Roger


IMPERATIVE CODE THAT WALKS TWO LISTS IN PARALLEL

In parallel, walk down list1 and list2. Upon finding list1-value (in
list1), return the corresponding value in list2.

<xsl:template name="walk-two-lists">
    <xsl:param name="list1" />
    <xsl:param name="list2" />
    <xsl:param name="list1-value" />

    <xsl:choose>
        <xsl:when test="$list1 = $list1-value">
            <xsl:value-of select="$list2" />
        </xsl:when>
        <xsl:when test="substring-before($list1, ' ') = $list1-value">
            <xsl:value-of select="substring-before($list2, ' ')" />
        </xsl:when>
        <xsl:otherwise>
            <xsl:call-template name="walk-two-lists">
                <xsl:with-param name="list1"
                           select="substring-after($list1, ' ')" />
                <xsl:with-param name="list2"
                           select=" substring-after($list2, ' '))" />
                <xsl:with-param name="list1-value"
                          select="$list1-value" />
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>

</xsl:template>

_______________________________________________________________________

XML-DEV is a publicly archived, unmoderated list hosted by OASIS
to support XML implementation and development. To minimize
spam in the archives, you must subscribe before posting.

[Un]Subscribe/change address: http://www.oasis-open.org/mlmanage/
Or unsubscribe: xml-dev-unsubscribe@lists.xml.org
subscribe: xml-dev-subscribe@lists.xml.org
List archive: http://lists.xml.org/archives/xml-dev/
List Guidelines: http://www.oasis-open.org/maillists/guidelines.php





[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index]


News | XML in Industry | Calendar | XML Registry
Marketplace | Resources | MyXML.org | Sponsors | Privacy Statement

Copyright 1993-2007 XML.org. This site is hosted by OASIS