Replaces nodes with strings.
<p:declare-step type="p:string-replace"> <input port="source" primary="true" content-types="xml html" sequence="false"/> <output port="result" primary="true" content-types="text xml html" sequence="false"/> <option name="match" as="xs:string" required="true"/> <option name="replace" as="xs:string" required="true"/> </p:declare-step>
The p:string-replace
step takes the document appearing on its source
port and replaces nodes matching the match
option
with a string that is computed using the XPath expression in the replace
option.
Ports:
Port | Type | Primary? | Content types | Seq? | Description |
---|---|---|---|---|---|
|
|
|
|
| The document to replace the nodes in. |
|
|
|
|
| The resulting document. |
Options:
The p:string-replace
step does the following:
It takes the document appearing on its source
port and holds the XSLT selection pattern in the match
option against this.
For each node matched:
The matched node becomes the context item (accessible with the dot operator .
).
The XPath expression in the replace
option is evaluated and the result is turned into a string.
If the matched node is an attribute, the value of the attribute is replaced with this string.
If the document-node is matched, the full document will be replaced by the string (and the result will therefore be a text document).
In all other cases, the full node is replaced by the string.
So this step replaces the matched node(s) with the result of a dynamically evaluated expression. This doesn’t mean this expression can’t be a constant: see the Basic usage example). However, it allows you to do all kinds of nifty calculations, based on where the match is: see the Advanced usage example.
This step replaces matched nodes with strings. If you need to replace matched nodes with full documents, have a look at the p:replace
step.
The following example simply replaces the thing’s <contents>
element with a (constant) description:
Source document:
<thing> <contents/> </thing>
Pipeline document:
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0"> <p:input port="source"/> <p:output port="result"/> <p:string-replace match="thing/contents" replace="'This is a thing of beauty!'"/> </p:declare-step>
Result document:
<thing>This is a thing of beauty!</thing>
Please notice the single quotes around the value in the replace
option. This option must not hold just some value but an
XPath expression. This means that if you need a constant string, you need to write it as an XPath string, therefore the
single quotes.
If the match
option matches an attribute, the value of the attribute is
replaced:
Source document:
<thing description="notfilledinyet"/>
Pipeline document:
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0"> <p:input port="source"/> <p:output port="result"/> <p:string-replace match="thing/@description" replace="'This is a thing of beauty!'"/> </p:declare-step>
Result document:
<thing description="This is a thing of beauty!"/>
The following example fills empty description
attributes with a value based on the index/occurrence of the parent
<thing>
element and the value of its name
attribute:
Source document:
<things> <thing name="brick" description=""/> <thing name="mortar" description=""/> <thing name="door" description="A door"/> </things>
Pipeline document:
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0"> <p:input port="source"/> <p:output port="result"/> <p:string-replace match="thing/@description[. eq '']" replace="'Thing ' || count(../preceding-sibling::thing) + 1 || ': ' || ../@name"/> </p:declare-step>
Result document:
<things> <thing name="brick" description="Thing 1: brick"/> <thing name="mortar" description="Thing 2: mortar"/> <thing name="door" description="A door"/> </things>
Notice that to be able to perform this trick, the description
attribute must already be there! A <thing>
element
without such an attribute will not be changed. So if you have content where this is lacking, you’ll need to prepare it. In this case we
use the p:add-attribute
step to add a description
attribute to any <thing>
element that is lacking one
first:
Source document:
<things> <thing name="brick" description=""/> <thing name="screw"/> <thing name="mortar" description=""/> <thing name="door" description="A door"/> </things>
Pipeline document:
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0"> <p:input port="source"/> <p:output port="result"/> <p:add-attribute match="thing[empty(@description)]" attribute-name="description" attribute-value=""/> <p:string-replace match="thing/@description[. eq '']" replace="'Thing ' || count(../preceding-sibling::thing) + 1 || ': ' || ../@name"/> </p:declare-step>
Result document:
<things> <thing name="brick" description="Thing 1: brick"/> <thing description="Thing 2: screw" name="screw"/> <thing name="mortar" description="Thing 3: mortar"/> <thing name="door" description="A door"/> </things>
Options can also be set using the <p:with-option>
element. If you use this for the replace
option, make sure that
you pass the expression in the replace
option as a string. If you don’t, it will get evaluated by
the pipeline, before the invocation of the p:string-replace
step, and that is very probably not what you intend. Here is an example of how to do this
right, based on the first example of Advanced usage:
Source document:
<things> <thing name="brick" description=""/> <thing name="mortar" description=""/> </things>
Pipeline document:
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="3.0"> <p:input port="source"/> <p:output port="result"/> <p:string-replace match="thing/@description"> <p:with-option name="replace" select="'''Thing '' || count(../preceding-sibling::thing) + 1 || '': '' || ../@name'"/> </p:string-replace> </p:declare-step>
Result document:
<things> <thing name="brick" description="Thing 1: brick"/> <thing name="mortar" description="Thing 2: mortar"/> </things>
If you accidentally write the p:with-option/@select
as the value of the p:string-replace/@replace
attribute in
Advanced usage (an easy and probable mistake to make), the XProc processor will raise an error:
The expression in the p:with-option/@select
is executed by the pipeline first and results in:
'Thing 1:'
This is not a valid XPath expression…
The p:string-replace
step tries to evaluate Thing 1:
as an expression and fails miserably (but rightly).
p:string-replace
preserves all document-properties of the document(s) appearing on its source
port.
There is one exception: if the resulting document contains only text, the content-type
document-property is changed to
text/plain
and the serialization
document-property is removed.
If an attribute called xml:base
is added or changed, the base URI of the element is updated accordingly. See also category
Base URI related.
This description of the p:string-replace
step is for XProc version: 3.1. This is a required step (an XProc 3.1 processor must support this).
The formal specification for the p:string-replace
step can be found here.
The p:string-replace
step is part of categories:
The p:string-replace
step is also present in version:
3.0.