Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>I compute the xpath for the current node then do one of the following...</p> </blockquote> <p>This is likely to be your inefficiency - if you're recalculating the path right back to the root every time you're likely to be looking at an O(N<sup>2</sup>) algorithm. Without seeing your XSLT this is rather speculative, but you might be able to trim this a bit by using parameters to pass the current path down the recursion - if your main algorithm is based on a standard identity template</p> <pre><code>&lt;xsl:template match="@*|node()"&gt; &lt;xsl:copy&gt;&lt;xsl:apply-templates select="@*|node()" /&gt;&lt;/xsl:copy&gt; &lt;/xsl:template&gt; </code></pre> <p>then change it to something like</p> <pre><code>&lt;xsl:template match="@*|node()"&gt; &lt;xsl:param name="curPath" /&gt; &lt;xsl:copy&gt; &lt;xsl:apply-templates select="@*|node()"&gt; &lt;xsl:with-param name="curPath" select="concat($curPath, '/', name())" /&gt; &lt;/xsl:apply-templates&gt; &lt;/xsl:copy&gt; &lt;/xsl:template&gt; </code></pre> <p>or whatever your logic is for building the paths you need. Now in your specific templates for the nodes you want to massage you already have the path to their parent node and you don't have to walk all the way up to the root every time.</p> <p>You might need to add a</p> <pre><code>&lt;xsl:template match="/"&gt; &lt;xsl:apply-templates /&gt; &lt;/xsl:template&gt; </code></pre> <p>so you don't get a double slash at the front of <code>$curPath</code></p> <hr> <blockquote> <p>The xpaths are hardcoded in the xslt as a string in a global variable</p> </blockquote> <p>If instead of a string you represented this mapping in an XML structure then you could make use of the <em>key</em> mechanism to speed up your lookups:</p> <pre><code>&lt;xsl:variable name="rtfLookupTable"&gt; &lt;lookuptable&gt; &lt;val xpath="/first/xpath/expression" id="1" /&gt; &lt;val xpath="/second/xpath/expression" id="2" /&gt; &lt;!-- ... --&gt; &lt;/lookuptable&gt; &lt;/xsl:variable&gt; &lt;xsl:variable name="lookupTable" select="msxsl:node-set($rtfLookupTable)" /&gt; &lt;xsl:key name="valByXpath" match="val" use="@xpath" /&gt; </code></pre> <p>(add <code>xmlns:msxsl="urn:schemas-microsoft-com:xslt"</code> to your <code>xsl:stylesheet</code>). Or if you want to avoid using the <code>node-set</code> extension function then an alternative definition could be</p> <pre><code>&lt;xsl:variable name="lookupTable" select="document('')//xsl:variable[name='rtfLookupTable']" /&gt; </code></pre> <p>which works by treating the stylesheet itself as a plain XML document.</p> <p>Keys across multiple documents get a bit fiddly in XSLT 1.0 but it can be done, essentially you have to switch the current context to point to the <code>$lookupTable</code> before calling the key function, so you need to save the current context in variables to let you refer to it later:</p> <pre><code>&lt;xsl:template match="text()"&gt; &lt;xsl:param name="curPath" /&gt; &lt;xsl:variable name="dot" select="." /&gt; &lt;xsl:variable name="slash" select="/" /&gt; &lt;xsl:for-each select="$lookupTable"&gt; &lt;xsl:variable name="valId" select="key('valByXpath', $curPath)/@id" /&gt; &lt;xsl:choose&gt; &lt;xsl:when test="$valId"&gt; &lt;xsl:value-of select="$slash//Value[@id = $valId]" /&gt; &lt;!-- or however you extract the right Value --&gt; &lt;/xsl:when&gt; &lt;xsl:otherwise&gt; &lt;xsl:value-of select="$dot" /&gt; &lt;/xsl:otherwise&gt; &lt;/xsl:choose&gt; &lt;/xsl:for-each&gt; &lt;/xsl:template&gt; </code></pre> <hr> <p>Or indeed, why not just let the XSLT engine do the hard work for you. Rather than representing your mapping as a string</p> <pre><code>/path/to/node1_1:/path/to/node2_2 </code></pre> <p>represent it as templates directly</p> <pre><code>&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"&gt; &lt;!-- copy everything as-is apart from exceptions below --&gt; &lt;xsl:template match="@*|node()"&gt; &lt;xsl:copy&gt;&lt;xsl:apply-templates select="@*|node()" /&gt;&lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;!-- delete the RealValuesRoot --&gt; &lt;xsl:template match="RealValuesRoot" /&gt; &lt;xsl:template match="/path/to/node1"&gt; &lt;xsl:copy&gt;&lt;xsl:value-of select="//Value[id='1']" /&gt;&lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;xsl:template match="/path/to/node2"&gt; &lt;xsl:copy&gt;&lt;xsl:value-of select="//Value[id='2']" /&gt;&lt;/xsl:copy&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p>I'm sure you can see how the specific templates could easily be auto-generated from your existing mapping using some sort of template mechanism (which could even be another XSLT).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload