XQuery Update Script for Creating a Custom Operation
To demonstrate creating a custom operation, suppose that you have a task where you need to
convert an attribute into an element and insert it inside another element. A specific example
would be if you have a project with a variety of <image>
elements where a
deprecated @alt
attribute was used for the description and you want to convert
all instances of that attribute into an element with the same name and insert it as the first
child of the <image>
element.
Thus, the task is to convert this attribute into an element with the same name and insert it as the first child of the image element.
An XQuery Update script can be used to implement the new custom XML refactoring operation. The second requirement is an XML Refactoring operation descriptor file that contains the path to the XQuery Update script.
Example of an XQuery Update Script for Creating a Custom Operation to Convert an Attribute to an Element
- Iterates over all elements from the document that have the specified local name and namespace.
- Finds the attribute that will be converted to an element.
- Computes the QName of the new element to be inserted and inserts it as the first child of the parent element.
(:
XQuery document used to implement 'Convert attribute to element'
operation from XML Refactoring tool.
:)
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method "xml";
declare option output:indent "no";
(: Local name of the attribute's parent element. :)
declare variable $element_localName as xs:string external;
(: Namespace of the attribute's parent element. :)
declare variable $element_namespace as xs:string external;
(: The local name of the attribute to be converted :)
declare variable $attribute_localName as xs:string external;
(: The namespace of the attribute to be converted :)
declare variable $attribute_namespace as xs:string external;
(: Local name of the new element. :)
declare variable $new_element_localName as xs:string external;
(: Namespace of the new element. :)
declare variable $new_element_namespace as xs:string external;
(: Convert attribute to element:)
for $node in //*
(: Find the attribute to convert :)
let $attribute :=
$node/@*[local-name() = $attribute_localName and
($attribute_namespace = '<ANY>' or $attribute_namespace = namespace-uri())]
(: Compute the prefix for the new element to insert :)
let $prefix :=
for $p in in-scope-prefixes($node)
where $new_element_namespace = namespace-uri-for-prefix($p, $node)
return $p
(: Compute the qname for the new element to insert :)
let $new_element_qName :=
if (empty($prefix) or $prefix[1] = '') then $new_element_localName
else $prefix[1] || ':' || $new_element_localName
where ('<ANY>' = $element_localName or local-name($node) = $element_localName)
and
($element_namespace = '<ANY>' or $element_namespace = namespace-uri($node))
return
if (exists($attribute)) then
(insert node element {QName($new_element_namespace, $new_element_qName)}
{string($attribute)} as first into $node,
delete node $attribute)
else ()
Example of an Operation Descriptor File That References the XQuery Script for Creating a Custom Operation to Convert an Attribute to an Element
After you have developed the XQuery script (for example, named convert-attribute-to-element.xq), you have to create an XML Refactoring operation descriptor (for example, named convert-attribute-to-element.xml) that references the stylesheet and provides descriptions and possible values for its parameters. This descriptor is used by the application to load the operation details such as name, description, or parameters.
<?xml version="1.0" encoding="UTF-8"?>
<refactoringOperationDescriptor
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.oxygenxml.com/ns/xmlRefactoring"
id="convert-attribute-to-element"
name="Convert attribute to element">
<description>Converts the specified attribute to an element.
The new element will be inserted as first child of the attribute's
parent element.</description>
<script type="XQUERY_UPDATE" href="convert-attribute-to-element.xq"/>
<parameters>
<description>Specify the attribute to be converted to element.</description>
<section label="Parent element">
<elementParameter id="elemID">
<localName label="Name" name="element_localName" allowsAny="true">
<description>Local name of the parent element.</description>
</localName>
<namespace label="Namespace" name="element_namespace" allowsAny="true">
<description>Local name of the parent element</description>
</namespace>
</elementParameter>
</section>
<section label="Attribute">
<attributeParameter dependsOn="elemID">
<localName label="Name" name="attribute_localName">
<description>Name of the attribute to be converted.</description>
</localName>
<namespace label="Namespace" name="attribute_namespace" allowsAny="true">
<description>Namespace of the attribute to be converted.</description>
</namespace>
</attributeParameter>
</section>
<section label="New element">
<elementParameter>
<localName label="Name" name="new_element_localName">
<description>The name of the new element.</description>
</localName>
<namespace label="Namespace" name="new_element_namespace">
<description>The namespace of the new element.</description>
</namespace>
</elementParameter>
</section>
</parameters>
</refactoringOperationDescriptor>
Results
After you have created these files, copy them into a folder scanned by Oxygen XML Developer Eclipse plugin when it loads the custom operation. When the XML Refactoring tool is started again, you will see the created operation.
Since various parameters can be specified, this custom operation can also be used for other similar tasks. The following image shows the parameters that can be specified in the example of the custom operation to convert an attribute to an element:
Debugging XQuery Refactoring Operations
You can use the XQuery trace() function to generate debugging information messages in the application's Results view.
The Saxon processor used for XQuery update processing also supports the EXPath extensions, which also allow you to write debugging information to an output file.