Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read a .properties file inside a .xsl file?

I have an XSL file which uses a a static website link as shown below:

<xsl:template match="my_match">

    <xsl:variable name="variable1">
        <xsl:value-of select="sel1/Label = 'Variable1'"/>
    </xsl:variable>
    <xsl:copy-of select="sites:testPath('http://testsite.com/services/testService/v1.0', $fname, $lname,
     $email , $zip, $phone, $comments, $jps, boolean($myvar), string(cust/@custID), string(@paID))"/>
</xsl:template>

My question is that how to read a properties file(key value pair) in the xsl file. so in my properties file (e.g. site.properties) I have a key called site i.e. site=testsite.com/services/testService/v1.0

I want to use this site key in place of specifying url value in the xsl i.e. http://testsite.com/services/testService/v1.0. The reason for doing this is that this link changes depending on the various environments.

Is this possible? Please give your suggestions or a sample code if possible...Also if this is not possible...is there any work-around?

like image 949
Sameer Malhotra Avatar asked Dec 01 '10 15:12

Sameer Malhotra


2 Answers

As a proof of concept:

Input .properties file:

# You are reading the ".properties" entry.
! The exclamation mark can also mark text as comments.
website = http://example.com
language = English
key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".

Stylesheet:

<?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"
  xmlns:f="Functions"
  version="2.0">

  <xsl:variable name="properties" select="unparsed-text('.properties')" as="xs:string"/>

  <xsl:template match="/" name="main">
    <xsl:value-of select="f:getProperty('language')"/>
  </xsl:template>

  <xsl:function name="f:getProperty" as="xs:string?">
    <xsl:param name="key" as="xs:string"/>
    <xsl:variable name="lines" as="xs:string*" select="
      for $x in 
        for $i in tokenize($properties, '\n')[matches(., '^[^!#]')] return
          tokenize($i, '=')
        return translate(normalize-space($x), '\', '')"/>
    <xsl:sequence select="$lines[index-of($lines, $key)+1]"/>
  </xsl:function>

</xsl:stylesheet>

The f:getProperty('language') will return 'English'.

See this as a proof of concept, this needs to be improved in many ways since it does not handle many of the different ways a .properties file can be authored.

I belive Alejandro or Dimitrie probably could improve this many times.

like image 80
Per T Avatar answered Oct 14 '22 02:10

Per T


For an XSLT 1.0 solution, you could use an external (parsed) general entity in an XML file that will load the properties file as part of the XML content.

For example, if you had a properties file like this, named site.properties:

foo=x
site=http://testsite.com/services/testService/v1.0
bar=y

You could create a simple XML file, named properties.xml that "wraps" the content of the properties file and loads it using an external parsed general entity:

<!DOCTYPE properties [
  <!ENTITY props SYSTEM "site.properties">
]>
<properties>
 &props;
</properties>

Then, within your XSLT you can load that properties.xml using the document() function and obtain the value for a given key:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:variable name="props" select="document('properties.xml')" />
    <xsl:template match="/">
        <output>
            <example1> 
                <!--simple one-liner -->
                <xsl:value-of select="substring-before(
                                        substring-after($props, 
                                                        concat('site','=')),
                                        '&#xA;')" />
            </example1>
            <example2>
                <!--using a template to retrieve the value 
                    of the "site" property -->
                <xsl:call-template name="getProperty">
                    <xsl:with-param name="propertiesFile" select="$props"/>
                    <xsl:with-param name="key" select="'site'"/>
                </xsl:call-template>
            </example2>
            <example3>
                <!--Another example using the template to retrieve 
                    the value of the "foo" property, 
                    leveraging default param value for properties -->
                <xsl:call-template name="getProperty">
                    <!--default $propertiesFile defined in the template, 
                        so no need to specify -->
                    <xsl:with-param name="key" select="'foo'"/>
                </xsl:call-template>
            </example3>
        </output>

    </xsl:template>

    <!--Retrieve a property from a properties file by specifying the key -->
    <xsl:template name="getProperty">
        <xsl:param name="propertiesFile" select="$props"/>
        <xsl:param name="key" />
        <xsl:value-of select="substring-before(
                                 substring-after($propertiesFile, 
                                                 concat($key,'=')), 
                                 '&#xA;')" />
    </xsl:template>

</xsl:stylesheet>

When applied to any XML input the stylesheet above will produce the following output:

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <example1>http://testsite.com/services/testService/v1.0</example1>
   <example2>http://testsite.com/services/testService/v1.0</example2>
   <example3>x</example3>
</output>

Note: this strategy will only work if the content of the properties file is "XML safe". If it were to contain characters, like & or < it would result in an XML parsing error when the properties.xml file is loaded.

like image 20
Mads Hansen Avatar answered Oct 14 '22 00:10

Mads Hansen