xsl-list
[Top] [All Lists]

RE: Replace values based on external files

2005-01-14 02:54:54
This needs an extension function such as dyn:evaluate, because you need to
evaluate XPath expressions that aren't hard-coded in the stylesheet. You
probably want the variant of this in Saxon called saxon:evaluate-node(),
which is designed specifically to handle XPath expressions in source XML
documents, and takes the namespace context for the XPath expression from the
element node in which it is contained.

Implementing this efficiently is not easy, because you don't want to copy
the whole source document each time you find a node whose value needs to be
replaced. In effect you want to build a list of nodes that need to be
changed, together with their replacement values, and then you want to do a
single scan of the source document testing each node to see if it is in this
list. Unfortunately the intermediate data structure - a mapping from nodes
to replacement values - is not easily represented in the XPath data model.
I'd try doing it using generate-id(), something like this:

<xsl:variable name="source" select="/">

<xsl:variable name="replacements">
  <xsl:for-each select="replace">
    <replace>
      <xsl:for-each select="$source/saxon:evaluate-node(current()/xpath)">
        <node><xsl:value-of select="generate-id(.)"/></node>
      </xsl:for-each>
      <xsl:copy-of select="with"/>
    </replace>
  </xsl:for-each>
</xsl:variable>

<xsl:key name="n" match="node" use="."/>

<xsl:template match="*">
  <xsl:copy>
  <xsl:apply-templates select="@*"/>
  <xsl:variable name="replacement" 
      select="$replacements/key('n', generate-id(current()))"/>
  <xsl:choose>
    <xsl:when test="$replacement">
      <xsl:value-of select="$replacement/../with"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates/>
    </
  </
</

<xsl:template match="@*">
  <xsl:variable name="replacement" 
      select="$replacements/key('n', generate-id(current()))"/>
  <xsl:choose>
    <xsl:when test="$replacement">
      <xsl:attribute name="{name(.)}" namespace="{namespace-uri(.)}" 
                     select="$replacement/../with"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy/>
    </
  </
</

Another way of tackling this problem would be by generating a stylesheet to
do it. That would remove the need for extension functions.

Michael Kay
http://www.saxonica.com/

-----Original Message-----
From: Robert Soesemann [mailto:rsoesemann(_at_)sapient(_dot_)com] 
Sent: 14 January 2005 09:28
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] Replace values based on external files

Hello,

I need to implement a XSL that will replace text values in file1.xml
based on replacement information in file2.xml.

file2.xml provides an XPath that points to an attribute / 
element value
and a replacement value. The XML has the form of:

<mapping>
    <!-- should replace @attribute1 value that are 'foo' of 
all element1
elements in file1.xml with 'bar'-->
    <replace>  
        <xpath>//element1/@attribute1[.='foo']</xpath>
        <with>bar</with>
    </replace>
    <replace>
        ...                    <!-- other replacement operations -->
    </replace>
    ...
</mapping>

Is there an easy way to dynamically generate replacement 
instructions in
my XSL. I thought of extracting replacement information from file2.xml
with the document function.


Any help is much welcome.

Robert

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--




--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



<Prev in Thread] Current Thread [Next in Thread>