2

I replace in memory XML node based on specific path before ingestion into NoSQL (marklogic) database.

Input: /doc1.xml

<image xmlns="http://coin/decimal">
      <DE>
         <denomination>1pf</denomination>
            <reverse>rye stalks</reverse>
            <obverse>oak sprig</obverse>
            <before>Anglo–Saxons</before>
      </DE>
      <GBP>
          <denomination>1p</denomination>
            <reverse>Arms</reverse>
            <obverse>Queen</obverse>
            <before>Anglo–Saxons</before>
      </GBP>
</image>

I replace the /before:image/before:DE/before:before value to a parameter value Xsl:

const beforeXsl =
 fn.head(xdmp.unquote(
`  <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:before="http://coin/decimal"  version="2.0">
 
    <xsl:template match="/Q{http://coin/decimal}image/Q{http://coin/decimal}DE/Q{http://coin/decimal}before">
            <xsl:element name="{local-name()}">
                <xsl:value-of select="$replace"/>
            </xsl:element>
    </xsl:template>
 
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
 
  </xsl:transform>
`));
 
xdmp.xsltEval(beforeXsl, doc, params)

Expected output:

<image xmlns="http://coin/decimal">
      <DE>
         <denomination>1pf</denomination>
            <reverse>rye stalks</reverse>
            <obverse>oak sprig</obverse>
            <before>Anglo-Dutch</before>
      </DE>
      <GBP>
          <denomination>1p</denomination>
            <reverse>Arms</reverse>
            <obverse>Queen</obverse>
            <before>Anglo–Saxons</before>
      </GBP>
</image>

I try to parameterize my xsl, but got the error:

[javascript] XSLT-BADPATTERN: MarkLogic extension syntax used, EQNames are not supported in XSLT mode
Chris
  • 123
  • 9
  • See if this helps: https://stackoverflow.com/a/34762628/3016153 – michael.hor257k Oct 09 '21 at 21:28
  • @Mads Hansen and @michael.hor257k, Thanks for the help. - The Qname works in other XSL editor but not in Marklogic. - I use static EQname because I don’t know other way to pass the path as params. Fiona’s provide that `xdmp:path` is right ON. Now I can pass in the path as params. - She fixes up what I missed: `namespace`. If the sample document is with–different or without namespace then it is transformed incorrectly. I hope I make my points clear. And we are very pleased to see the xslt happens. – Chris Oct 10 '21 at 16:05

2 Answers2

1

Why! Shouldn’t it have been

var params = {};
params.nsProduct = "http://coin/decimal"
params.qPath = "/before:image/before:DE/before:before"
params.replaceValue="Anglo-Dutch"

const implReplace = fn.head(xdmp.unquote(
`
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:before="http://coin/decimal"  
    exclude-result-prefixes="#all" version="2.0">
    
    <xsl:param name="nsProduct"/>
    <xsl:param name="qPath"/>
    <xsl:param name="replaceValue" as="xs:anyAtomicType"/>
    
    <xsl:template match="node()[(xdmp:path(.) eq $qPath)]">
        <xsl:variable name="replace">
            <xsl:element name="{local-name()}" namespace="{$nsProduct}">
                <xsl:value-of select="$replaceValue"/>
            </xsl:element>
        </xsl:variable>
        <xsl:sequence select="$replace"/>
    </xsl:template>
    
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    
</xsl:transform>

`));

xdmp.xsltEval(implReplace, doc, params)
Fiona Chen
  • 1,358
  • 5
  • 16
0

EQname are not supported in XSLT 2.0 stylesheets. You are attempting to use them in the @match expression.

Instead, use the before namespace-prefix that you already have defined in the XPath in your @match expression in your XSLT:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:before="http://coin/decimal"  version="2.0">

  <xsl:param name="replace"/>

  <xsl:template match="/before:image/before:DE/before:before">
        <xsl:element name="{local-name()}">
            <xsl:value-of select="$replace"/>
        </xsl:element>
  </xsl:template>

  <xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:transform>

You will also need to define an xsl:param or xsl:variable for the $replace, which is currently undefined.

Mads Hansen
  • 63,927
  • 12
  • 112
  • 147