Name

lxreplace — Make replacements or deletions in an XML document

Synopsis

lxreplace [ -xmlns[:prefix]=uri ...] -q target-query [ -r replace-query | -t template | -n rename-query | -a add-query | -@ attr-name-query attr-value-query | -d ] [ input-file ]

Description

lxreplace allows nodes in an XML document (elements, attributes and text) to be replaced, deleted, or renamed. The nodes to be changed are specified by an XPath. Their replacements are specified by either an XPath expression or an XSLT template.

The input-file argument may be a URI instead of a filename. If no input-file argument is given, standard input is used.

-xmlns[:prefix]=uri

binds a prefix (or the default namespace) to a URI for use in XPath queries.

-q target-query

an XPath specifying the nodes to be processed. Nodes that match the target-query are processed; the others are left unchanged. How the nodes are processed depends on which of the -r, -t, -n, and -d flags is used. Unless the -t is used, this query is streamed.

-r replace-query

an XPath which is used to construct the replacement for matched nodes. The replace-query is evaluated relative to the matched node. If the result is an element then it is processed recursively before replacing the original matched node.

If the matched node is an attribute, then it is deleted if the replace-query returns an empty node set. Otherwise the value of the attribute is replaced by the string value of the result.

-t template

an XSLT template which is used to construct the replacement for matched nodes. This is done by constructing an XSLT stylesheet containing the template in a rule whose match attribute is the target-query.

In the stylesheet, the prefix xsl is bound to the XSL namespace. A low-priority template rule is included that provides an identity transform for nodes not matched by the template. For convenience, a number of entities are defined for use in the template:

&this;

Copies the current node and recursively processes its attributes and children. Equivalent to <xsl:copy><xsl:apply-templates select='@*|node()'/></xsl:copy>.

&attrs;

Processes the attributes of the current node. Equivalent to <xsl:apply-templates select='@*'/>

&children;

Processes the children of the current node. Equivalent to <xsl:apply-templates select='node()'/>.

&text;

Copies the text of the current node. Equivalent to <xsl:value-of select='.'/>.

&space;

Inserts a space character. Equivalent to <xsl:text> </xsl:text>.

&newline;

Inserts a newline character. Equivalent to <xsl:text>&#10;</xsl:text>.

-n rename-query

an XPath which is used to rename the matched nodes. The rename-query is evaluated relative to the matched node and the result is interpreted as a QName. A QName (qualified name) is either a plain name such as table or a prefixed name such as xhtml:table. Only elements and attributes can be renamed.

-a add-query

an XPath which is used to construct nodes to be added to the matched nodes, which must be elements. The add-query is evaluated relative to the matched node. The result must be a node-set and the nodes are added to the matched node as attributes or children. If multiple attributes with the same name are added, the one last in document order wins.

-@ attr-name-query attr-value-query

two XPaths which are used to construct the names and values of attributes to be added to the matched nodes, which must be elements. The attr-name-query is evaluated relative to the matched node and the result interpreted as a QName, the name of a new attribute to be added. The attr-value-query is evaluated relative to the matched node and is converted to a string and used as the value of the new attribute. Any existing attribute with the same name is replaced.

-d

This causes the matched nodes to be simply deleted, rather than replaced. It is equivalent to "-r expr" where expr is an XPath that selects an empty node set.

If none of -r, -t, -n, -@, and -d is given the effect is equivalent to "-r node()", which replaces matched nodes with their children. That is, it "unwraps" the children of the nodes.

Note about quoting

It is usually necessary to quote the query and template arguments because they contain characters significant to the shell such as *. It is generally best to use single quotes for this, and use double quotes when needed inside the value. In some cases it is quite difficult to find an appropriate quoting.

If you need an XPath whose value is a fixed string (as is commonly the case when renaming elements and attributes), you must doubly quote it; for example '"foo"'. The outer quotes are consumed by the shell, so if you used 'foo' the XPath would evaulate to any <foo> children of the current node instead of to the string "foo".

Note about streaming

Except when -t is used, lxreplace streams the input document, so that only the subtree rooted at the matched node and its ancestors are accessible when the replace-query, rename-query, or add-query is evaluated. If it is necessary to access other parts of the document to construct the replacement, use the -t form instead.

Examples

lxreplace -q '*'

This replaces all elements with their children, in effect deleting all element markup.

lxreplace -q 'meta' -d

This deletes all <meta> elements.

lxreplace -q entity -n '"ent"'

This changes the name of all <entity> elements to ent. Note the double quoting.

lxreplace -q entity -n @type

This changes the name of all <entity> elements to the value of their type attribute.

lxreplace -q entity -t '<entity text="{.}">&attrs;&children;</entity>'

This adds an attribute text to all <entity> elements, whose value is the text content of the element. This will only work if the element doesn't already have a text attribute, otherwise the old value will be copied back by the call to &attrs;. We could avoid this by using a more complicated template:

lxreplace -q entity -t '<entity>&attrs;<xsl:attribute name="text">&text;</xsl:attribute>&children;</entity>'

which constructs the name attribute after copying the old ones.

lxreplace -q entity -r @text

This replaces all <entity> elements with the value of their text attribute.

lxreplace -q w -a 'w/@*'

This adds the attributes from any nested <w> elements to their parent <w> elements.

lxreplace -q w -@ '"text"' .

This adds an attribute called text to all <w> elements, with a value equal to the text content of the element. Note the double quoting.