简体   繁体   中英

Ant xmlproperty task fails due to validation error

I want to extract an application version from a DITA map file. The ditamap file is valid and looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd">
<map id="user-manual">
    <title><ph keyref="product"/> User Manual</title>
    <topicmeta>
        <prodinfo>
            <prodname><keyword keyref="product"/></prodname>
            <vrmlist>
                <vrm version="4" release="3" modification="0"/>
            </vrmlist>
        </prodinfo>
    </topicmeta>
    <!--
        [...]
    -->
</map>

The information I want to get is in the <vrm> element.

"Easy peasy," I think to myself. So I use Ant's <xmlproperty> task to just load this XML file.

<project default="test">
    <!-- notice @validate -->
    <xmlproperty file="path/to/user-manual.ditamap" validate="false"/>
    <target name="test">
        <echo>${map.topicmeta.prodinfo.vrmlist.vrm(version)}</echo>
    </target>
</project>

I don't want it to validate because Ant isn't going to find map.dtd.

Loading the file returns an error:

java.io.FileNotFoundException: /home/user/user-manual/map.dtd (No such file or directory)

If I remove the <!DOCTYPE> declaration or add a nested <xmlcatalog> with the path to the DTD, the file loads and I can use the properties from it.

I tested this with Ant 1.7.1 and 1.9.4. Is this a bug with Ant, or am I misunderstanding how Ant loads XML properties and the purpose of the validate attribute?

How can I make Ant obey my will?

I recommend to not use the <xmlproperty> for this. Please have a look at the docs :

For example, with semantic attribute processing enabled, this XML property file:

<root>
  <properties>
    <foo location="bar"/>
    <quux>${root.properties.foo}</quux>
  </properties>
</root>

is roughly equivalent to the following fragments in a build.xml file:

<property name="root.properties.foo" location="bar"/>
<property name="root.properties.quux" value="${root.properties.foo}"/>

So the name of the properties you set is generated using their paths to the root element, so they rely on the structure of your DITA Map. But many elements in DITA may be set at different positions on your DITA Map. That means, if you move your metadata to another parent element, the property name changes and your build fails. This is probably not, what you want.

I'd recommend to grab those values via XSLT and than set the properties. That way, you could, for example, say, "give me the first occurance of that element with a simple //foo[1] XPath selector. Further on, you have the power of XSLT and XPath to slice values, format dates and so on before setting a property.

Update You can use the oops consultancy Ant xmltask for that. It is very easy to set a property using <copy> :

<copy path="//critdates/created/@date"
            property="document.date"
            append="false"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM