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开发者_JS百科 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>
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
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">
Node can (if using XSLT 2.0+) also be adressed via * because they lie in another namespace .
<xsl:copy-of select="document(concat($artifactCoordinate,'-pom.xml'))/*:project/*:properties)"/>
This can be just convienent or especially useful if the namespace is unknown. In this case the nice side effect is that if the namespace is marked this way the nodes from the other namespace don't get an annotation - which is not wanted in our case.
精彩评论