RE: [xsl] Replace values based on external files

Subject: RE: [xsl] Replace values based on external files
From: "Robert Soesemann" <rsoesemann@xxxxxxxxxxx>
Date: Fri, 14 Jan 2005 11:08:55 +0100
Hello Michael,

Thanks for the input. As I need this for batch processing many files I
think I would rather like to use your second altervative of meta
stylesheets.
I read about his but I have never done it. It would be absolutly great
if you (or somebody else) could come up with a draft how to implement
this with meta stylesheets.

Regards,

Robert

-----Original Message-----
From: Michael Kay [mailto:mike@xxxxxxxxxxxx]
Sent: Freitag, 14. Januar 2005 10:55
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: RE: [xsl] Replace values based on external files


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@xxxxxxxxxxx]
> Sent: 14 January 2005 09:28
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> 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

Current Thread