1

I would like to define an xslt sheet where variables and access functions are defined. The sheet should be then used within another stylesheet. The main idea is to have single point of defining key value pairs for interface mapping tasks. The following code does not produce a result.

EDIT: The real world problem is a system integration problem. Think of a "type"-property. In System A the type "Car" is encoded with the key "1". In System B (where i have to import a message from System A) the type "Car" is encoded with the key "X". Example: 1 <-> Car <-> X. So when i map messages from System A to messages from System B i need kind of a map. I would like to define this map at a single place (single XSLT sheet) and use it in multiple other XSLT sheet (via incluce command). As long with the map i also would like to define convenient access functions like this: getTargetKey(mapWhereTheKeyIsIn, 'sourceKey'). So where ever i have to map message from System A into the schema of System B i would like to type: <Type><xsl:value-of select="getTargetKey(typeMap, '1')" /><Type> and get <Type>X</Type>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
  <xsl:output method="text" encoding="UTF-8"/>                
    <xsl:variable name="var1">
         <Entry key="1" value="ABC" />
         <Entry key="2" value="CDF" />
    </xsl:variable>
  <xsl:template match="/">   
       <xsl:value-of select="myFunc('var1', '1')" />
  </xsl:template>
            <xsl:function name="myFunc">
              <xsl:param name="variable_name"/>
              <xsl:param name="key"/>
              <xsl:value-of select="document('')/*/xsl:variable[@name=$variable_name]/Entry[@key = $key]/@value"/>
            </xsl:function>   
</xsl:stylesheet>

Sample Input

<?xml version="1.0" encoding="UTF-8"?>
<order_system_a type="1" />

Desired Output

<?xml version="1.0" encoding="UTF-8"?>
<order_system_b type="X" />
3
  • Why would you need to do this? Just pass the variable itself as the first argument to the function. Please, define the real problem you are solving, then many people will be able to give a solution. Commented Dec 23, 2011 at 18:18
  • That's a good first step. Yet something needed you forgot to provide is the XML document (as small as possible, please), and the wanted result. This seems as an easy task that, of course, doesn't need the impossible dynamic variable selection that you are asking for. Once you provide the missing data, I will give you a solution. Commented Dec 23, 2011 at 18:55
  • I've added a minimal input and output. Commented Dec 23, 2011 at 19:39

1 Answer 1

2

Here is the requested generic solution to the problem:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my" exclude-result-prefixes="my xs">
 <xsl:import href="C:/temp/delete/GlobalTypeMappings.xsl"/>
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="order_system_a">
  <order_system_b>
   <xsl:apply-templates select="@*"/>
  </order_system_b>
 </xsl:template>

 <xsl:template match="order_system_a/@type">
  <xsl:attribute name="type" select=
   "my:convertType('order_system_a', 'order_system_b', .)"/>
 </xsl:template>
</xsl:stylesheet>

C:/temp/delete/GlobalTypeMappings.xsl:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my" exclude-result-prefixes="my xs">

 <xsl:key name="kMapFromLocal" match="map"
  use="concat(@system, '+', @local-type)"/>

 <xsl:key name="kMapFromValue" match="map"
  use="concat(@system, '+', @value)"/>

 <my:TypeMappings>
  <map system="order_system_a" local-type="1" value="type1"/>
  <map system="order_system_a" local-type="2" value="type2"/>
  <map system="order_system_a" local-type="3" value="type3"/>
  <map system="order_system_a" local-type="4" value="type4"/>

  <map system="order_system_b" local-type="X" value="type1"/>
  <map system="order_system_b" local-type="Y" value="type2"/>
  <map system="order_system_b" local-type="Z" value="type3"/>
  <map system="order_system_b" local-type="T" value="type4"/>

  <!-- Other type mappings here -->
 </my:TypeMappings>

 <xsl:function name="my:convertType" as="xs:string?">
  <xsl:param name="pfromSystem" as="xs:string"/>
  <xsl:param name="ptoSystem" as="xs:string"/>
  <xsl:param name="pfromValue" as="xs:string"/>

  <xsl:variable name="vthisDoc" select="document('')"/>

  <xsl:sequence select=
   "key('kMapFromValue',
         concat($ptoSystem,
               '+',
                key('kMapFromLocal',
                    concat($pfromSystem, '+', $pfromValue),
                    $vthisDoc
                    )
                     /@value
                ),
          $vthisDoc
        )
         /@local-type
   "/>
 </xsl:function>
</xsl:stylesheet>

When the above transformation is applied to the provided XML document:

<order_system_a type="1" />

the wanted, correct result is produced:

<order_system_b type="X"/>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.