Skip to main content
IBM developerWorks / Developer Centers
Sign In | Register dW
UrbanCode
  • Products & Solutions
    • UrbanCode Deploy – Deployment Automation
    • UrbanCode Release
    • UrbanCode Build
    • UrbanCode Velocity
    • Continuous Release
  • Plugins
  • Docs
  • Videos
  • Forum
  • Blogs
  • Events

Tag Archives:XPath

Manipulating XML files with XPath strings in IBM UrbanCode Deploy

XMLXPath
Tim McMackin / January 16, 2017 / 2 comments

I’m learning that people really want to manipulate XML files with their IBM UrbanCode Deploy servers! We get so many questions about the Update XML With XPath automation step (both through the forum and through direct contact) that I wrote an article about some common things that come up when people want to edit XML files as part of their deployment automation: Using the Update XML with Xpath step.

… and we still get a ton of XPath questions!

The most common use case seems to be a server configuration that needs an edit when a new application or version of an application gets deployed. However, this step can edit just about any XML file, though there are some gotchas and idiosyncrasies that are listed in the article. (I might go into some detail about those in a later post.)

The basics are pretty simple: first, you give the step the name and location of an XML file or files. Then you give it some rules for changes to make in the XML file. To tell the step to change some text, for example, you give it an XPath string that points to the text, then a little text “arrow” (->), and then the new text.

For example, here’s some sample XML from the article:

<?xml version="1.0" encoding="UTF-8"?>
<testFile>
  <myData>
    <data name="filePath" value="/opt/sampleDirectory"/>
    <data name="textData">Here is some text.</data>
    <data att1="one" att2="two" name="attributes" value="something"/>
  </myData>
</testFile>

To change an attribute value, you use an XPath string that points to that attribute, and then you put in the new text. For example, to change the “/opt/sampleDirectory” to “/usr/otherDirectory”, put this in the Replace with text field:

//testFile/myData/data[@value]/@value->/usr/otherDirectory

To change the text of a node, refer to it as “text()”, for example:

//testFile/myData/data[@name='textData']/text()->Some new text content.

Run both of those operations and the XML looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<testFile>
  <myData>
    <data name="filePath" value="/usr/otherDirectory"/>
    <data name="textData">Some new text content.</data>
    <data att1="one" att2="two" name="attributes" value="something"/>
  </myData>
</testFile>

There are also steps to add and remove XML nodes.

Got an unusual file that you need to make changes to as part of your deployment automation? Keep the XPath questions coming in the forum and we’ll answer as many as we can.

 

Using the Update XML with Xpath step

PluginsXMLXPath
Tim McMackin / March 6, 2015 / 7 comments

Overview

We get a lot of forum questions about the use of the Update XML with Xpath step of the File Utils plugin, so I figured I’d post some examples to help people along. It’s a very useful step because it can update XML files on the fly, which is great for changing configurations on a deployment.

To use this step, make sure you’ve got the File Utils automation plugin installed. You can use this step in any component process or generic process.

To use this step, you’ll need a basic knowledge of XPath, which is how you specify where to add, remove, or change the XML code. There are lots of resources out there for learning XPath, but here’s a good one: http://www.w3schools.com/xpath/

For full details on the File Utils plugin and the Update XML with XPath step, see its documentation page. In short, this step has several fields in which you can specify changes to XML files:

Insert XML
This field adds XML nodes to the document. You specify one or more XPath expression -> content pairs, separated by newlines. The XPath expression points to the parent node, and the content is inserted under that node.
Remove
This field removes elements or attributes to remove. You specify one or more XPath expressions and the step removes the matching elements.
Replace with text
This field replaces the content of text nodes or attributes with new text. You specify one or more XPath expression -> content pairs, separated by newlines. The XPath expression points to the parent node or attribute, and the content is inserted in that node or attribute.
Set Attributes
This field updates the attributes that you specify, similar to the Replace with text field. You specify one or more expression -> content pairs, separated by newlines. The XPath expression points to one or more attributes, and the content becomes the new value of that attribute.

Here’s a picture of the step properties, which include each of the above fields. To use it, open a component process or generic process and drag the Update XML with Xpath step to the process.

Screenshot of the Update XML with Xpath step, showing the different fields that you can use to edit XML code

Use cases

Here are some common use cases of the step. I’ll use the following example XML file in these use cases:

<?xml version="1.0" encoding="UTF-8"?>
<testFile>
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Here is some text.</data>
<data att1="one" att2="two" name="attributes" value="something"/>
</myData>
</testFile>

Use case 1: Inserting XML nodes

To insert XML nodes, specify the parent of the new node with XPath code. For example, to add a new <data> node next to the existing nodes, I specify the parent of the <data> nodes. The Insert XML field of the Update XML File with XPath step looks like this:

//testFile/myData-><data name="myNewData"/>

The updated file has the new <data> node:

<?xml version="1.0" encoding="UTF-8"?><testFile>
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Here is some text.</data>
<data att1="one" att2="two" name="attributes" value="something"/>
<data name="myNewData"/>
</myData>
</testFile>

The step can also accept more complicated XPath expressions. For example, you can use an XPath predicate to specify a node with a certain attribute. The following code inserts a node under the <data> node that has the attribute name="filePath":

//testFile/myData/data[@name='filePath']-><info/>

The resulting XML looks like this:

<?xml version="1.0" encoding="UTF-8"?><testFile>
<myData>
<data name="filePath" value="/opt/sampleDirectory">
<info/>
</data>
<data name="textData">Here is some text.</data>
<data att1="one" att2="two" name="attributes" value="something"/>
</myData>
</testFile>

Use case 2: Changing an attribute value

The Set Attributes field of the step lets you change an attribute. All you have to do is point to the attribute with an XPath expression and provide the new value. For example, the following code changes the value of an attribute on a <data> node.

//testFile/myData/data[@name='filePath']/@value->/home/user1

The resulting XML looks like this:

<?xml version="1.0" encoding="UTF-8"?><testFile>
<myData>
<data name="filePath" value="/home/user1"/>
<data name="textData">Here is some text.</data>
<data att1="one" att2="two" name="attributes" value="something"/>
</myData>
</testFile>

XPath expressions can target multiple places in the XML code. For example, the following code selects the <data> nodes that have a value attribute and changes both of those attributes:

//testFile/myData/data[@value]/@value->newValue

The resulting XML looks like this:

<?xml version="1.0" encoding="UTF-8"?><testFile>
<myData>
<data name="filePath" value="newValue"/>
<data name="textData">Here is some text.</data>
<data att1="one" att2="two" name="attributes" value="newValue"/>
</myData>
</testFile>

Use case 3: Changing a text node

Accessing text nodes (that is, the text that’s inside the content of a node) is a little different than accessing an attribute. Here’s an example of code to change the content of a text node, which goes in the Replace with text field of the step:

//testFile/myData/data[@name='textData']/text()->Some new text content.

The resulting XML looks like this:

<?xml version="1.0" encoding="UTF-8"?><testFile>
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Some new text content.</data>
<data att1="one" att2="two" name="attributes" value="something"/>
</myData>
</testFile>

Use case 4: Changing attributes

Changing attributes is straightforward. In the Set Attributes field, specify an XPath expression that points to one or more attributes and then provide the content for the attributes. For example:

//testFile/myData/data[@att1='one']/@att2->NewAttributeValue

The resulting XML looks like this:

<?xml version="1.0" encoding="UTF-8"?><testFile>
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Here is some text.</data>
<data att1="one" att2="NewAttributeValue" name="attributes" value="something"/>
</myData>
</testFile>

Use case 5: Removing XML nodes

To remove XML content, specify an XPath expression in the Remove field. Here’s a simple example that deletes one node:

//testFile/myData/data[@value='something']

The resulting XML looks like this:

<?xml version="1.0" encoding="UTF-8"?><testFile>
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Here is some text.</data>

</myData>
</testFile>

You can also remove attributes; just specify an attribute with the XPath expression, as in the following example:

//testFile/myData/data[@name='filePath']/@value

Common problems

1. Using quotes in the update content.

You don’t need to enclose your new content in quotes.

Wrong:

//testFile/myData/data[@value]/@value->"newValue"

Correct:

//testFile/myData/data[@value]/@value->newValue

2. Specifying the wrong location for the file.

If the file doesn’t change, be sure that you’ve got the right path to the file and the correct file name in the step. You can also select the Fail if no match found check box to prevent this problem.

Known issues

1. Namespaces without prefixes (internal work item jazz02:134075)

If your XML document has a default namespace (that is, a namespace that is specified without a prefix), the step won’t work.

For example, XPath expressions won’t work on the following document because its namespace does not have a prefix:

<?xml version="1.0" encoding="UTF-8"?>
<testFile xmlns="http://example.com/mynamespace">
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Here is some text.</data>
<data name="attributes" att1="one" att2="two" value="something"/>
</myData>
</testFile>

There are two possible workarounds for this issue:

First, you can assign a prefix to the namespace, as in the following example. Then, the step can process the XML data as usual, with no change in your XPath expressions.

<?xml version="1.0" encoding="UTF-8"?>
<testFile xmlns:mynamespace="http://example.com/mynamespace">
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Here is some text.</data>
<data name="attributes" att1="one" att2="two" value="something"/>
</myData>
</testFile>

If you don’t want to edit the XML file, another workaround (that does not require changing the XML file) is to use the local-name() function. With this technique, you replace the node names with a function that returns the name of the node without respect to its namespace. For example, the following code deletes a node:

//*[local-name()='testFile']/*[local-name()='myData']/*[local-name()='data' and @name='attributes']

The resulting XML code looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<testFile xmlns:mynamespace="http://example.com/mynamespace">
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Here is some text.</data>

</myData>
</testFile>

2. Inserting text nodes (internal work item jazz02:129806)

The Update XML with XPath step fails to add a text node if the node does not have one already. For example, the first <data> node in the following code does not have a text node like the second <data> node does:

<?xml version="1.0" encoding="UTF-8"?>
<testFile>
<myData>
<data name="filePath" value="/opt/sampleDirectory"/>
<data name="textData">Here is some text.</data>
<data att1="one" att2="two" name="attributes" value="something"/>
</myData>
</testFile>

If you use the following code in the Insert XML or Replace with text field, the step can’t add the text because there is no text node there currently.

Wrong:

//testFile/myData/data[@name='filePath']/text()->New text

As a workaround, add text as a child of the node and the step adds the text node automatically:

Correct:

//testFile/myData/data[@name='filePath']->New text

3. Resolving and removing DTDs

If your XML file has a doctype declaration, the step tries to retrieve the DTD and validate the XML file before it makes any changes. If the step can’t find that DTD, the step fails.

For example, the following XML file has a doctype declaration at the top:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
  "-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN"
  "http://java.sun.com/dtd/application_1_3.dtd">
<application>
        <module>
                <web>
                        <web-uri>myapp.war</web-uri>
                        <context-root>myapplication</context-root>
                </web>
        </module>
</application>

In this case, the agent that is running the step must be able to access the DTD at http://java.sun.com/dtd/application_1_3.dtd; otherwise the step fails.

Also note that DTD declarations like the one in the previous example are removed from the output of this step.

Testing with generic processes

When I’m working on processes that contain this step, I always test out the XML editing with a generic process first; it’s usually easier to test and debug my XML editing there than in a component process. My test process looks like this:

  1. Delete the edited copy of the XML file. I always leave my original XML file untouched and edit a copy, so I can compare with the original. (Make sure to make this step succeed whether it finds the edited copy of the file or not, or else it will fail the process if it can’t find the new file.)
  2. Make a copy of the XML file. By default, the Update XML with XPath step edits the file in place, so I like to make a copy for testing purposes.
  3. Edit the XML file with the Update XML with XPath step. Here’s where the process does the real work.

I hope that’s useful information. If you’ve got other questions, post them to the UrbanCode questions forum and I or someone else will try to help.

Date
April 2018 (2)
March 2018 (1)
February 2018 (1)
January 2018 (1)
December 2017 (1)
October 2017 (2)
September 2017 (6)
August 2017 (7)
July 2017 (5)
June 2017 (5)
May 2017 (7)
April 2017 (3)
Tags
Docker (4)
IBM UrbanCode Deploy (118)
Follow us on Twitter Find us on Facebook RSS Feed
  • Home
  • Products & Solutions
  • Docs
  • Videos
  • Forum
  • Blog
  • Events
  • Careers
  • Report Abuse
  • Terms of Use
  • Third Party Notice
  • IBM Privacy
IBM