[XML-DEV Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: 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@m... To rg> "xml-dev@lists.xml.org" <xml-dev@lists.xml.org> 03/20/2010 05:35 cc PM Subject 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] |
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|