2010-04-29 60 views
5

问候!XSLT文档函数在Maven POM上返回空结果

我想通过文档函数从XSLT中的不同Maven POM中提取一些属性。该脚本本身工作正常,但文档函数返回POM的空结果,只要我在项目标签中有xmlns =“http://maven.apache.org/POM/4.0.0”。如果我删除它,一切正常。

任何想法如何使它的工作,而离开它属于xmlns属性或为什么这不适用于该属性?

这才是我的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> 

,为了完整性,一个POM提取与 “坏” 的属性:

<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> 
+0

好问题(+1)。请参阅我的回答,以获取有关该问题的解释以及最常用的解决方案。 :) – 2010-04-29 12:58:04

回答

10

您的问题是POM提取使用默认命名空间。这意味着这些元素虽然前缀不明,但位于“http://maven.apache.org/POM/4.0.0”中 - 不在“无命名空间”中。

然而,在该XPath表达式,在XSLT代码:

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

名称projectproperties是无前缀。 XPath始终将前缀名称视为属于“无名称空间”。因此,找不到这样的元素并且没有选择节点。

解决方案:命名空间定义添加到您的<xsl:stylesheet>,让说:

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

在引用POM节点从someElementp:someElement任何表情然后重写元素名称。例如:

document(concat($artifactCoordinate,'-pom.xml'))/p:project/p:properties 
+0

谢谢迪米特雷 - 这个作品!现在,这个解决方案在我从文档函数调用中获得的每个元素中都提供了xmlns:pom =“...”,但是我希望找到一些方法来摆脱这种情况,也许在之前提供目标文档中的声明。 – Jan 2010-04-30 09:48:29

+0

@Jan:只需添加到''以下属性:'exclude-result-prefixes =“pom”' – 2010-04-30 12:53:25

+0

啊!这是一个很好的补充 - 谢谢。我还发现了一个通用的解决方案,可以满足我的特殊需求(请参阅我的答案)。 – Jan 2010-04-30 14:22:59

3

这是一个命名空间问题。源文档中的xmlns="http://maven.apache.org/POM/4.0.0"表示默认将所有元素放入XML文档中的“http://maven.apache.org/POM/4.0.0”命名空间。

如果你想在你的xslt中获取它们,你需要在你的xslt中声明这个名称空间(有或没有要使用的前缀),然后在选择元素时使用该名称空间。

例如,我猜你的例子中的模板是为了匹配POM中的“abcs”元素,是的?尝试添加在你的XSL命名空间的声明:“我要加入‘聚甲醛’作为标识此文档中的‘http://maven.apache.org/POM/4.0.0’命名空间的前缀”样式表,例如:

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

这给XSL说

然后选择元素或匹配模板时,使用前缀,如:

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

或通过与POM命名空间为默认宣告你的样式尝试没有前缀,像:

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

谢谢!可悲的是,“全局方法”对我不起作用 - 显然是因为我也有其他名称空间的标签。也许我的问题不够精确 - abcs在另一个命名空间。然而,每个前缀方法对我来说都很合适,就像Dimitre下面提到的那样。 – Jan 2010-04-30 09:45:44

+0

@Matt:如果你想在使用XPath选择元素时想要一个默认的命名空间,你需要使用'xpath-default-namespace'(XSLT 2.0或更高版本支持),如http://www.w3.org/TR/xslt20 /#前缀的-的QName。使用'xmlns =“...”'设置缺省名称空间只能配置样式表中XML文字的默认名称空间,XPath表达式不受影响。 – markusk 2010-05-02 05:09:42

+0

@markusk感谢您的澄清;我还没有使用xpath-default-namespace,但我确信在未来的某个时候它会派上用场! – 2010-05-05 08:54:54

1

节点可以(如果使用XSLT 2.0+),因为它们处于另一个命名空间也可以通过*不客气。

<xsl:copy-of select="document(concat($artifactCoordinate,'-pom.xml'))/*:project/*:properties)"/> 

这可以是convienent或特别有用如果名称空间是未知的。在这种情况下,好的副作用是,如果命名空间用这种方式标记,来自其他命名空间的节点不会得到注释 - 这在我们的例子中不是想要的。

+1

@Jan:'*:name'语法仅在XPath 2.0中受支持。 – 2010-04-30 15:59:35

+0

@Jan:另请注意,如果您使用XSLT 2.0或更高版本,则可以使用'xpath-default-namespace',如http://www.w3.org/TR/xslt20/#unprefixed-qnames中所述。 – markusk 2010-05-02 05:12:03

+0

@Dimitre:当然 - 对不起,我忘了添加那个细节(使用它)。 – Jan 2010-06-04 12:30:30