Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT Document function returns empty result on Maven POM

Greetings!

I want to extract some properties from different Maven POMs in a XSLT via the document function. The script itself works fine but the document function returns an empty result for the POM as long as I have the xmlns="http://maven.apache.org/POM/4.0.0" in the project tag. If I remove it, everything works fine.

Any idea how the make this work while leaving the xmlns attribute where it belongs or why this doesn't work with the attribute in place?

Here comes the relevant portion of my XSLT:

<xsl:template match="abcs">
 <xsl:variable name="artifactCoordinate" select="abc"/>
   <xsl:choose>
        <xsl:when test="document(concat($artifactCoordinate,'-pom.xml'))">
         <abc>
          <ID><xsl:value-of select="$artifactCoordinate"/></ID>
    <xsl:copy-of select="document(concat($artifactCoordinate,'-pom.xml'))/project/properties"/>
   </abc>
         </xsl:when>
            <xsl:otherwise>
       <xsl:message terminate="yes">
           Transformation failed: POM "<xsl:value-of select="concat($artifactCoordinate,'-pom.xml')"/>" doesn't exist. 
       </xsl:message>
      </xsl:otherwise> 

</xsl:choose> 

And, for completeness, a POM extract with the "bad" attribute:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- ... -->
<properties>
    <proalpha.version>[5.2a]</proalpha.version>
    <proalpha.openedge.version>[10.1B]</proalpha.openedge.version>
    <proalpha.optimierer.version>[1.1]</proalpha.optimierer.version>
    <proalpha.sonic.version>[7.6.1]</proalpha.sonic.version>
</properties>
 </project>
like image 498
Jan Avatar asked Apr 29 '10 07:04

Jan


2 Answers

Your problem is that the POM extract uses default namespace. This means that the elements, although unprefixed, are in the "http://maven.apache.org/POM/4.0.0" -- not in the "no namespace".

However, in this XPath expression, in the XSLT code:

document(concat($artifactCoordinate,'-pom.xml'))/project/properties

the names project and properties are unprefixed. XPath always treats unprefixed names as belonging to "no namespace". Hence, no such elements are found and no node is selected.

Solution: Add a namespace definition to your <xsl:stylesheet>, lets say:

  xmlns:p="http://maven.apache.org/POM/4.0.0"

Then rewrite element names in any expressions referencing POM nodes from someElement to p:someElement. For example:

document(concat($artifactCoordinate,'-pom.xml'))/p:project/p:properties
like image 90
Dimitre Novatchev Avatar answered Oct 05 '22 23:10

Dimitre Novatchev


This is a namespace problem. The xmlns="http://maven.apache.org/POM/4.0.0" in the source document means that all the elements are by default put into the "http://maven.apache.org/POM/4.0.0" namespace in the XML document.

If you want to get ahold of them in your xslt, you need to declare that namespace in your xslt (with or without a prefix to use) and then use that namespace when selecting your elements.

For example, I'm guessing that the template in your example is meant to match an "abcs" element in your POM, yes? Try adding a namespace declaration in your xsl:stylesheet, e.g.:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:pom="http://maven.apache.org/POM/4.0.0" version="1.0">

That says to the XSL "I want to add 'pom' as a prefix that identifies the 'http://maven.apache.org/POM/4.0.0' namespace in this document."

Then when selecting elements or matching templates, use that prefix, e.g.:

<xsl:template match="pom:abcs">

Or try it without the prefixes by declaring your stylesheet with the POM namespace as default, something like:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns="http://maven.apache.org/POM/4.0.0" version="1.0">
like image 23
Matt Gibson Avatar answered Oct 05 '22 22:10

Matt Gibson