Antony
Antony

Reputation: 976

How to change processing instruction to string value in XQuery

Sample XML

<root>
  <a>
    <text>VOL <?P _line?> <?range val?></text>
  </a>
  <a>
    <text><?x lp;80q?>sample</text>
  </a>
</root>

Expected output

<root>
  <a>
    <text>VOL <?P _line?>test</text>
  </a>
  <a>
    <text><?x lp;80q?>sample</text>
  </a>
</root>

I need change the Processing-instruction(range) to 'test' can you please help?

Upvotes: 1

Views: 295

Answers (2)

Michael Kay
Michael Kay

Reputation: 163322

Making a small change to a document is often easier using XSLT. Here is an XSLT 3.0 solution:

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:mode on-no-match="shallow-copy"/>
  <xsl:template match="processing-instruction(range)">test</xsl:template>
</xsl:transform>

Upvotes: 2

Ghislain Fourny
Ghislain Fourny

Reputation: 7279

The most natural way would be a copy-modify-return clause, however I think MarkLogic does not support the XQuery Update Facility.

A recursion would probably work, along the lines of:

declare function local:replace($element as element()) as element()
{
  element { node-name($element) } {
    for $child in $element/node()
    return typeswitch($child)
           case processing-instruction(range)
               return text { "test" }
           case element()
               return local:replace($child)
           default
               return $child
  }
};

let $doc :=
<root>
  <a>
    <text>VOL <?P _line?> <?range val?></text>
  </a>
  <a>
    <text><?x lp;80q?>sample</text>
  </a>
</root>
return local:replace($doc)

(This works with Saxon in oXygen, but this should be purely standard XQuery)

Note: use document { local:replace($doc/*) } instead if the input is a document node.

Upvotes: 4

Related Questions