You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
499 lines
22 KiB
XML
499 lines
22 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- **********************************************************************
|
|
* Copyright (C) 2017 by gempa GmbH
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as
|
|
* published by the Free Software Foundation, version 3.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Lesser Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*
|
|
* SC3ML 0.7 to QuakeML 1.2 RT stylesheet converter
|
|
* Author : Stephan Herrnkind
|
|
* Email : stephan.herrnkind@gempa.de
|
|
* Version : 2014.251.01
|
|
*
|
|
* ================
|
|
* Usage
|
|
* ================
|
|
*
|
|
* This stylesheet converts a SC3ML to a QuakeML-RT document. It may be
|
|
* invoked e.g. using xalan or xsltproc:
|
|
*
|
|
* xalan -in sc3ml.xml -xsl sc3ml_0.7__quakeml_1.2-RT.xsl -out quakeml.xml
|
|
* xsltproc -o quakeml.xml sc3ml_0.7__quakeml_1.2-RT.xsl sc3ml.xml
|
|
*
|
|
* ================
|
|
* Transformation
|
|
* ================
|
|
*
|
|
* QuakeML and SC3ML are quite similar schemas. Nevertheless some differences
|
|
* exist:
|
|
*
|
|
* - IDs : SC3ML does not enforce any particular ID restriction. An ID in
|
|
* SC3ML has no semantic, it simply must be unique. Hence QuakeML uses ID
|
|
* restrictions, a conversion of a SC3ML to a QuakeML ID must be performed:
|
|
* 'sc3id' -> 'smi:scs/0.7/sc3id'. If no SC3ML ID is available but QuakeML
|
|
* enforces one, a static ID value of 'NA' is used.
|
|
* - Position of 'magnitude' and 'stationMagnitude' nodes : Whereas SC3ML
|
|
* places these nodes under the 'origin' element, QuakeML-RT expects them on
|
|
* the same level as the 'origin' element. When moving these nodes the
|
|
* publicID of the parent 'origin' is copied to the 'originID' child node of
|
|
* the magnitude nodes (except an originID was specified in the SC3ML
|
|
* sources nodes).
|
|
*
|
|
* <EventParameters> <eventParameters>
|
|
* <origin publicID="foo"> <origin publicID="smi:scs/0.7/foo"/>
|
|
* <stationMagnitude/> <stationMagnitude>
|
|
* <originID>smi:scs/0.7/foo</originID>
|
|
* </stationMagnitude>
|
|
* <magnitude> <magnitude>
|
|
* <originID>bar</originID> <originID>smi:scs/0.7/bar</originID>
|
|
* </magnitude> </magnitude>
|
|
* </EventParameters> </eventParameters>
|
|
*
|
|
* - An 'event' in SC3ML and QuakeML-RT refers to its origins via
|
|
* 'originReference' elements. Since in SC3ML 'magnitude' elements are
|
|
* children of a 'origin' a connection of events and origins can be made.
|
|
* For the same mapping QuakeML-RT uses 'magnitudeReference' elements.
|
|
*
|
|
* - Renaming of nodes: The following table lists the mapping of names between
|
|
* both schema:
|
|
*
|
|
* Parent (SC3) SC3 name QuakeML name
|
|
* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
|
* seiscomp EventParameters eventParameters
|
|
* arrival weight timeWeight
|
|
* takeOffAngle takeoffAngle
|
|
* magnitude magnitude mag
|
|
* stationMagnitude magnitude mag
|
|
* amplitude amplitude genericAmplitude
|
|
* origin uncertainty originUncertainty
|
|
* waveformID resourceURI CDATA
|
|
* comment id id (attribute)
|
|
*
|
|
* - Enumerations: Both schema use enumerations. Numerous mappings are applied.
|
|
*
|
|
* - Unit conversion: SC3ML uses kilometer for origin depth, QuakeML uses meter
|
|
*
|
|
* - Unmapped nodes: The following nodes can not be mapped to the QuakeML
|
|
* schema, thus their data is lost:
|
|
*
|
|
* Parent Element lost
|
|
* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
|
* creationInfo modificationTime
|
|
* arrival timeUsed
|
|
* horizontalSlownessUsed
|
|
* backazimuthUsed
|
|
* focalMechanism evaluationMode
|
|
* evaluationStatus
|
|
* momentTensor method
|
|
* stationMomentTensorContribution
|
|
* status
|
|
* cmtName
|
|
* cmtVersion
|
|
* phaseSetting
|
|
*
|
|
* - Restriction of data size: QuakeML restricts string length of some
|
|
* elements. This length restriction is _NOT_ enforced by this
|
|
* stylesheet to prevent data loss. As a consequence QuakeML files
|
|
* generated by this XSLT may not validate because of these
|
|
* restrictions.
|
|
*
|
|
* ================
|
|
* Change log
|
|
* ===============
|
|
*
|
|
* * 08.09.2014: Fixed typo in event type conversion (meteo[r] impact)
|
|
*
|
|
* * 25.08.2014: Applied part of the patch proposed by Philipp Kaestli on
|
|
* seiscomp-l@gfz-potsdam.de
|
|
* - used public id of parent origin if origin id propertery of magnitude
|
|
* and station magnitudes is unset
|
|
* - fixed takeOffAngle conversion vom real (SC3ML) to RealQuantity
|
|
* (QuakeML)
|
|
*
|
|
* * 28.06.2017: Changed license from GPL to LGPL
|
|
*
|
|
********************************************************************** -->
|
|
<xsl:stylesheet version="1.0"
|
|
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
xmlns:scs="http://geofon.gfz-potsdam.de/ns/seiscomp3-schema/0.7"
|
|
xmlns:qml="http://quakeml.org/xmlns/quakeml/1.0"
|
|
xmlns="http://quakeml.org/xmlns/bed-rt/1.2"
|
|
xmlns:vs="http://quakeml.org/xmlns/vstypes/0.1"
|
|
xmlns:q="http://quakeml.org/xmlns/quakeml-rt/1.2"
|
|
exclude-result-prefixes="scs qml xsl">
|
|
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
|
|
<xsl:strip-space elements="*"/>
|
|
|
|
<!-- Define some global variables -->
|
|
<!-- CHANGE ME: Please change the ID_PREFIX to the reverse DNS name of your
|
|
institute -->
|
|
<xsl:variable name="ID_PREFIX" select="'smi:ch.ethz.sed/sc3a/'"/>
|
|
<xsl:variable name="PID" select="'publicID'"/>
|
|
|
|
<!-- Starting point: Match the root node and select the one and only
|
|
EventParameters node -->
|
|
<xsl:template match="/">
|
|
<xsl:variable name="scsRoot" select="."/>
|
|
<q:quakeml>
|
|
<xsl:for-each select="$scsRoot/scs:seiscomp/scs:EventParameters">
|
|
<eventParameters>
|
|
<!-- Mandatory publicID attribute -->
|
|
<xsl:attribute name="{$PID}">
|
|
<xsl:call-template name="convertOptionalID">
|
|
<xsl:with-param name="id" select="@publicID"/>
|
|
</xsl:call-template>
|
|
</xsl:attribute>
|
|
<!-- Move all origin/stationMagnitudes and origin/magitudes
|
|
to this level -->
|
|
<xsl:for-each select="scs:origin">
|
|
<xsl:for-each select="scs:stationMagnitude">
|
|
<xsl:apply-templates select="." mode="originMagnitude">
|
|
<xsl:with-param name="oID" select="../@publicID"/>
|
|
</xsl:apply-templates>
|
|
</xsl:for-each>
|
|
<xsl:for-each select="scs:magnitude">
|
|
<xsl:apply-templates select="." mode="originMagnitude">
|
|
<xsl:with-param name="oID" select="../@publicID"/>
|
|
</xsl:apply-templates>
|
|
</xsl:for-each>
|
|
</xsl:for-each>
|
|
|
|
<xsl:apply-templates/>
|
|
</eventParameters>
|
|
</xsl:for-each>
|
|
</q:quakeml>
|
|
</xsl:template>
|
|
|
|
<!-- Default match: Map node 1:1 -->
|
|
<xsl:template match="*">
|
|
<xsl:call-template name="genericNode"/>
|
|
</xsl:template>
|
|
|
|
<!-- Delete elements -->
|
|
<xsl:template match="scs:creationInfo/scs:modificationTime"/>
|
|
<xsl:template match="scs:comment/scs:id"/>
|
|
<xsl:template match="scs:arrival/scs:timeUsed"/>
|
|
<xsl:template match="scs:arrival/scs:horizontalSlownessUsed"/>
|
|
<xsl:template match="scs:arrival/scs:backazimuthUsed"/>
|
|
<xsl:template match="scs:arrival/scs:azimuth"/>
|
|
<xsl:template match="scs:arrival/scs:distance"/>
|
|
<xsl:template match="scs:arrival/scs:timeResidual"/>
|
|
<xsl:template match="scs:arrival/scs:weight"/>
|
|
<xsl:template match="scs:pick/scs:creationInfo"/>
|
|
<xsl:template match="scs:pick/scs:evaluationMode"/>
|
|
<xsl:template match="scs:pick/scs:methodID"/>
|
|
<xsl:template match="scs:pick/scs:phaseHint"/>
|
|
<xsl:template match="scs:magnitude/scs:comment"/>
|
|
<xsl:template match="scs:magnitude/scs:creationInfo"/>
|
|
<xsl:template match="scs:origin/scs:stationMagnitude"/>
|
|
<xsl:template match="scs:origin/scs:magnitude"/>
|
|
<xsl:template match="scs:origin/scs:quality"/>
|
|
<xsl:template match="scs:origin/scs:depthType"/>
|
|
<xsl:template match="scs:origin/scs:methodID"/>
|
|
<xsl:template match="scs:origin/scs:earthModelID"/>
|
|
<xsl:template match="scs:origin/scs:evaluationMode"/>
|
|
<xsl:template match="scs:origin/scs:creationInfo"/>
|
|
<xsl:template match="scs:event/scs:description"/>
|
|
<xsl:template match="scs:event/scs:creationInfo"/>
|
|
<xsl:template match="scs:focalMechanism/scs:evaluationMode"/>
|
|
<xsl:template match="scs:focalMechanism/scs:evaluationStatus"/>
|
|
<xsl:template match="scs:momentTensor/scs:method"/>
|
|
<xsl:template match="scs:momentTensor/scs:stationMomentTensorContribution"/>
|
|
<xsl:template match="scs:momentTensor/scs:status"/>
|
|
<xsl:template match="scs:momentTensor/scs:cmtName"/>
|
|
<xsl:template match="scs:momentTensor/scs:cmtVersion"/>
|
|
<xsl:template match="scs:momentTensor/scs:phaseSetting"/>
|
|
|
|
|
|
<!-- event -->
|
|
<xsl:template match="scs:event">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:apply-templates select="@*"/>
|
|
<xsl:apply-templates/>
|
|
|
|
<!-- Create network magnitude references referenced by origins of
|
|
this event -->
|
|
<xsl:for-each select="scs:originReference">
|
|
<xsl:for-each select="../../scs:origin[@publicID=current()]/scs:magnitude/@publicID">
|
|
<xsl:element name="magnitudeReference">
|
|
<xsl:call-template name="convertID">
|
|
<xsl:with-param name="id" select="string(.)"/>
|
|
</xsl:call-template>
|
|
</xsl:element>
|
|
</xsl:for-each>
|
|
</xsl:for-each>
|
|
|
|
<!-- Add the MVS likelihood as child of event -->
|
|
<xsl:for-each select="../scs:origin/scs:magnitude/scs:type[.='MVS']">
|
|
<xsl:for-each select="../scs:comment/scs:id[.='likelihood']">
|
|
<xsl:element name='vs:likelihood'>
|
|
<xsl:value-of select="../scs:text"/>
|
|
</xsl:element>
|
|
</xsl:for-each>
|
|
</xsl:for-each>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- Converts a scs magnitude/stationMagnitude to a qml
|
|
magnitude/stationMagnitude -->
|
|
<xsl:template match="*" mode="originMagnitude">
|
|
<xsl:param name="oID"/>
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:apply-templates select="@*"/>
|
|
<!-- if no originID element is available, create one with
|
|
the value of the publicID attribute of parent origin -->
|
|
<xsl:if test="not(scs:originID)">
|
|
<originID>
|
|
<xsl:call-template name="convertID">
|
|
<xsl:with-param name="id" select="$oID"/>
|
|
</xsl:call-template>
|
|
</originID>
|
|
</xsl:if>
|
|
<xsl:apply-templates/>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- event type, enumeration differs slightly -->
|
|
<xsl:template match="scs:event/scs:type">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:variable name="v" select="current()"/>
|
|
<xsl:choose>
|
|
<xsl:when test="$v='induced earthquake'">induced or triggered event</xsl:when>
|
|
<xsl:when test="$v='meteor impact'">meteorite</xsl:when>
|
|
<xsl:when test="$v='not locatable'">other</xsl:when>
|
|
<xsl:when test="$v='outside of network interest'">other</xsl:when>
|
|
<xsl:when test="$v='duplicate'">other</xsl:when>
|
|
<xsl:otherwise><xsl:value-of select="$v"/></xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- origin depth, SC3ML uses kilometer, QML meter -->
|
|
<xsl:template match="scs:origin/scs:depth/scs:value|scs:origin/scs:depth/scs:uncertainty|scs:origin/scs:depth/scs:lowerUncertainty|scs:origin/scs:depth/scs:upperUncertainty">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:value-of select="current() * 1000"/>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- evaluation status, enumeration of QML does not include 'reported' -->
|
|
<xsl:template match="scs:origin/scs:evaluationStatus|scs:pick/scs:evaluationStatus">
|
|
<xsl:variable name="v" select="current()"/>
|
|
<xsl:if test="$v!='reported'">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:value-of select="$v"/>
|
|
</xsl:element>
|
|
</xsl:if>
|
|
</xsl:template>
|
|
|
|
<!-- data used wave type, enumeration differs slightly -->
|
|
<xsl:template match="scs:dataUsed/scs:waveType">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:variable name="v" select="current()"/>
|
|
<xsl:choose>
|
|
<xsl:when test="$v='P body waves'">P waves</xsl:when>
|
|
<xsl:when test="$v='long-period body waves'">body waves</xsl:when>
|
|
<xsl:when test="$v='intermediate-period surface waves'">surface waves</xsl:when>
|
|
<xsl:when test="$v='long-period mantle waves'">mantle waves</xsl:when>
|
|
<xsl:otherwise><xsl:value-of select="$v"/></xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- origin uncertainty description, enumeration of QML does not include 'probability density function' -->
|
|
<xsl:template match="scs:origin/scs:uncertainty|scs:preferredDescription">
|
|
<xsl:variable name="v" select="current()"/>
|
|
<xsl:if test="$v!='probability density function'">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:value-of select="$v"/>
|
|
</xsl:element>
|
|
</xsl:if>
|
|
</xsl:template>
|
|
|
|
<!-- origin arrival, since SC3ML does not include a publicID it is generated from pick and origin id -->
|
|
<xsl:template match="scs:arrival">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:attribute name="{$PID}">
|
|
<xsl:call-template name="convertID">
|
|
<xsl:with-param name="id" select="concat(scs:pickID, '#', ../@publicID)"/>
|
|
</xsl:call-template>
|
|
</xsl:attribute>
|
|
<!--comment/-->
|
|
<xsl:apply-templates/>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- Value of ID nodes must be converted to a qml identifier -->
|
|
<xsl:template match="scs:agencyURI|scs:authorURI|scs:pickID|scs:methodID|scs:earthModelID|scs:amplitudeID|scs:originID|scs:stationMagnitudeID|scs:preferredOriginID|scs:preferredMagnitudeID|scs:originReference|scs:filterID|scs:slownessMethodID|scs:pickReference|scs:amplitudeReference|scs:referenceSystemID|scs:triggeringOriginID|scs:derivedOriginID|momentMagnitudeID|scs:preferredFocalMechanismID|scs:focalMechanismReference|scs:momentMagnitudeID|scs:greensFunctionID">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:apply-templates select="@*"/>
|
|
<xsl:call-template name="valueOfIDNode"/>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- arrival/weight -> arrival/timeWeight
|
|
<xsl:template match="scs:arrival/scs:weight">
|
|
<xsl:call-template name="genericNode">
|
|
<xsl:with-param name="name" select="'timeWeight'"/>
|
|
</xsl:call-template>
|
|
</xsl:template>-->
|
|
|
|
<!-- arrival/takeOffAngle -> arrival/takeoffAngle -->
|
|
<xsl:template match="scs:arrival/scs:takeOffAngle">
|
|
<xsl:element name="takeoffAngle">
|
|
<xsl:element name="value">
|
|
<xsl:value-of select="."/>
|
|
</xsl:element>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- stationMagnitude/magnitude -> stationMagnitude/mag -->
|
|
<xsl:template match="scs:stationMagnitude/scs:magnitude|scs:magnitude/scs:magnitude">
|
|
<xsl:call-template name="genericNode">
|
|
<xsl:with-param name="name" select="'mag'"/>
|
|
</xsl:call-template>
|
|
</xsl:template>
|
|
|
|
<!-- amplitude/amplitude -> amplitude/genericAmplitude -->
|
|
<xsl:template match="scs:amplitude/scs:amplitude">
|
|
<xsl:call-template name="genericNode">
|
|
<xsl:with-param name="name" select="'genericAmplitude'"/>
|
|
</xsl:call-template>
|
|
</xsl:template>
|
|
|
|
<!-- origin/uncertainty -> origin/originUncertainty -->
|
|
<xsl:template match="scs:origin/scs:uncertainty">
|
|
<xsl:call-template name="genericNode">
|
|
<xsl:with-param name="name" select="'originUncertainty'"/>
|
|
</xsl:call-template>
|
|
</xsl:template>
|
|
|
|
<!-- waveformID: SCS uses a child element 'resourceURI', QML
|
|
inserts the URI directly as value -->
|
|
<xsl:template match="scs:waveformID">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:apply-templates select="@*"/>
|
|
<xsl:if test="scs:resourceURI">
|
|
<xsl:call-template name="convertID">
|
|
<xsl:with-param name="id" select="scs:resourceURI"/>
|
|
</xsl:call-template>
|
|
</xsl:if>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- comment: SCS uses a child element 'id', QML an attribute 'id' -->
|
|
<xsl:template match="scs:comment">
|
|
<xsl:element name="{local-name()}">
|
|
<xsl:if test="scs:id">
|
|
<xsl:attribute name="id">
|
|
<xsl:call-template name="convertID">
|
|
<xsl:with-param name="id" select="scs:id"/>
|
|
</xsl:call-template>
|
|
</xsl:attribute>
|
|
</xsl:if>
|
|
<xsl:apply-templates/>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- Generic transformation of all attributes of an element. If the
|
|
attribute name is 'eventID' it is transfered to a QML id -->
|
|
<xsl:template match="@*">
|
|
<xsl:variable name="attName" select="local-name()"/>
|
|
<xsl:attribute name="{$attName}">
|
|
<xsl:choose>
|
|
<xsl:when test="$attName=$PID">
|
|
<xsl:call-template name="convertID">
|
|
<xsl:with-param name="id" select="string(.)"/>
|
|
</xsl:call-template>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:value-of select="string(.)"/>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:attribute>
|
|
</xsl:template>
|
|
|
|
<!--
|
|
************************************************************************
|
|
Named Templates
|
|
************************************************************************
|
|
-->
|
|
|
|
<!-- Generic and recursively transformation of elements and their
|
|
attributes -->
|
|
<xsl:template name="genericNode">
|
|
<xsl:param name="name"/>
|
|
<xsl:param name="reqPID"/>
|
|
<xsl:variable name="nodeName">
|
|
<xsl:choose>
|
|
<xsl:when test="$name">
|
|
<xsl:value-of select="$name"/>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:value-of select="local-name()"/>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
<xsl:element name="{$nodeName}">
|
|
<xsl:apply-templates select="@*"/>
|
|
<xsl:if test="$reqPID">
|
|
<xsl:attribute name="{$PID}">
|
|
<xsl:call-template name="convertOptionalID">
|
|
<xsl:with-param name="id" select="@publicID"/>
|
|
</xsl:call-template>
|
|
</xsl:attribute>
|
|
</xsl:if>
|
|
<xsl:apply-templates/>
|
|
</xsl:element>
|
|
</xsl:template>
|
|
|
|
<!-- Converts and returns value of an id node
|
|
<xsl:template name="valueOfIDNode">
|
|
<xsl:call-template name="convertOptionalID">
|
|
<xsl:with-param name="id" select="string(.)"/>
|
|
</xsl:call-template>
|
|
</xsl:template> -->
|
|
|
|
<!-- Carlo from Enrico - Converts and returns value of an id node -->
|
|
<xsl:template name="valueOfIDNode">
|
|
<xsl:call-template name="convertOptionalID">
|
|
<xsl:with-param name="id" select="translate(., '>', '')"/>
|
|
</xsl:call-template>
|
|
</xsl:template>
|
|
|
|
<!-- Converts a scs id to a quakeml id. If the scs id is not set
|
|
the constant 'NA' is used -->
|
|
<xsl:template name="convertOptionalID">
|
|
<xsl:param name="id"/>
|
|
<xsl:choose>
|
|
<xsl:when test="$id">
|
|
<xsl:call-template name="convertID">
|
|
<xsl:with-param name="id" select="$id"/>
|
|
</xsl:call-template>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:call-template name="convertID">
|
|
<!--xsl:with-param name="id" select="concat('NA-', generate-id())"/-->
|
|
<xsl:with-param name="id" select="'NA'"/>
|
|
</xsl:call-template>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:template>
|
|
|
|
<!-- Converts a scs id to a quakeml id -->
|
|
<xsl:template name="convertID">
|
|
<xsl:param name="id"/>
|
|
<xsl:value-of select="concat($ID_PREFIX, translate($id, ' :', '__'))"/>
|
|
</xsl:template>
|
|
</xsl:stylesheet>
|
|
|