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
2
  • See if this helps: stackoverflow.com/a/34762628/3016153 Commented Oct 9, 2021 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. Commented Oct 10, 2021 at 16:05

2 Answers 2

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)
Sign up to request clarification or add additional context in comments.

1 Comment

Ms. Fiona: The answer hits the mark! Thank you very much!
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.