xpathantxmltask

XMLPath from ant using XMLTasks can't match if XML file has elements in different name spaces


I'm trying to get some matching using XMLTasks to replace some values in a xml file but it keeps failing due to no match. Using other tools it says that my xpath is correct but I can't figure out what's wrong.

Here the file I'm searching:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
    <type>org.netbeans.modules.apisupport.project</type>
    <configuration>
        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
            <code-name-base>simple.server.extension.cardgame</code-name-base>
            <suite-component/>
            <module-dependencies>
                <dependency>
                    <code-name-base>marauroa.lib</code-name-base>
                    <build-prerequisite/>
                    <compile-dependency/>
                    <run-dependency>
                        <release-version>3</release-version>
                        <specification-version>8</specification-version>
                    </run-dependency>
                </dependency>
                <dependency>
                    <code-name-base>simple.server.lib</code-name-base>
                    <build-prerequisite/>
                    <compile-dependency/>
                    <run-dependency>
                        <release-version>0-1</release-version>
                        <specification-version>0.2</specification-version>
                    </run-dependency>
                </dependency>
            </module-dependencies>
            <public-packages>
                <package>dreamer.card.game</package>
                <package>dreamer.card.game.model.events</package>
                <package>dreamer.card.game.price</package>
                <package>dreamer.card.game.storage</package>
                <package>simple.server.extension</package>
                <package>simple.server.extension.card</package>
            </public-packages>
            <class-path-extension>
                <runtime-relative-path>ext/extension/x.jar</runtime-relative-path>
                <binary-origin>../../Simple Marauroa Java/Card Game Extension/dist/x.jar</binary-origin>
            </class-path-extension>
            <class-path-extension>
                <runtime-relative-path>ext/extension/y.jar</runtime-relative-path>
                <binary-origin>../../Simple Marauroa Java/Card Game interface/dist/y.jar</binary-origin>
            </class-path-extension>
        </data>
    </configuration>
</project>

And this is the path expression I'm using:

/project/configuration/data/class-path-extension[1]/runtime-relative-path/text()

Here are the relevant parts of the task I'm trying to run:

<target name="s" depends="-define-xmltasks">
        <propertyselector property="subprojects" match="original.project.dir(.*)" select="\1"/>
        <for list="${subprojects}" param="subproject">
            <sequential>
                <xmltask source="nbproject/project.xml" dest="nbproject/project.xml" failWithoutMatch="true">
                    <replace path="/project/configuration/data/class-path-extension[@{subproject}]/runtime-relative-path/text()" 
                             withText="ext/extension/${extension-lib@{subproject}.dist.jar}"/>
                    <replace path="/project/configuration/data/class-path-extension[@{subproject}]/binary-origin/text()" 
                             withText="${original.project.dir@{subproject}}/dist/${extension-lib@{subproject}.dist.jar}"/>
                </xmltask>
            </sequential>
        </for>
    </target>

@{subproject} resolves to a number and already tried changing it for a number but has the same effect. Any idea?


Solution

  • And this is the path expression I'm using:

    /project/configuration/data/class-path-extension[1]/runtime-relative-path/text()
    

    One way to deal with unprefixed names that are in a non-empty (default) namespace, is to specify the name as a predicate.

    Here is an XPath expression written in this style that selects the wanted node(s):

       /*[name()='project']
         /*[name()='configuration']
           /*[name()='data']
             /*[name()='class-path-extension'][1]
               /*[name()='runtime-relative-path']
                 /text()
    

    XSLT - based verification:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="/">
      <xsl:copy-of select=
      "/*[name()='project']
         /*[name()='configuration']
           /*[name()='data']
             /*[name()='class-path-extension'][1]
               /*[name()='runtime-relative-path']
                 /text()
      "/>
     </xsl:template>
    </xsl:stylesheet>
    

    When this transformation is applied on the provided XML document:

    <project xmlns="http://www.netbeans.org/ns/project/1">
        <type>org.netbeans.modules.apisupport.project</type>
        <configuration>
            <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
                <code-name-base>simple.server.extension.cardgame</code-name-base>
                <suite-component/>
                <module-dependencies>
                    <dependency>
                        <code-name-base>marauroa.lib</code-name-base>
                        <build-prerequisite/>
                        <compile-dependency/>
                        <run-dependency>
                            <release-version>3</release-version>
                            <specification-version>8</specification-version>
                        </run-dependency>
                    </dependency>
                    <dependency>
                        <code-name-base>simple.server.lib</code-name-base>
                        <build-prerequisite/>
                        <compile-dependency/>
                        <run-dependency>
                            <release-version>0-1</release-version>
                            <specification-version>0.2</specification-version>
                        </run-dependency>
                    </dependency>
                </module-dependencies>
                <public-packages>
                    <package>dreamer.card.game</package>
                    <package>dreamer.card.game.model.events</package>
                    <package>dreamer.card.game.price</package>
                    <package>dreamer.card.game.storage</package>
                    <package>simple.server.extension</package>
                    <package>simple.server.extension.card</package>
                </public-packages>
                <class-path-extension>
                    <runtime-relative-path>ext/extension/x.jar</runtime-relative-path>
                    <binary-origin>../../Simple Marauroa Java/Card Game Extension/dist/x.jar</binary-origin>
                </class-path-extension>
                <class-path-extension>
                    <runtime-relative-path>ext/extension/y.jar</runtime-relative-path>
                    <binary-origin>../../Simple Marauroa Java/Card Game interface/dist/y.jar</binary-origin>
                </class-path-extension>
            </data>
        </configuration>
    </project>
    

    the XPath expression is evaluated and the selected node is copied to the output:

    ext/extension/x.jar
    

    Note: For incremental building and verification of XPath expressions you can use a tool such as the XPath visualizer. This tool has helped many thousands of people learn XPath the fun way.