6

问候!

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

知道如何在将 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>
4

3 回答 3

11

您的问题是 POM 提取使用 default namespace。这意味着元素虽然没有前缀,但在“ 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
于 2010-04-29T12:56:34.103 回答
3

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

如果您想在您的 xslt 中获取它们,您需要在您的 xslt 中声明该命名空间(使用或不使用前缀),然后在选择元素时使用该命名空间。

例如,我猜测您示例中的模板旨在匹配您的 POM 中的“abcs”元素,是吗?尝试在 xsl:stylesheet 中添加命名空间声明,例如:

<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 表示“我想添加 'pom' 作为前缀,用于标识本文档中的 ' http://maven.apache.org/POM/4.0.0 ' 命名空间。”

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

<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">
于 2010-04-29T12:46:41.187 回答
1

节点(如果使用 XSLT 2.0+)也可以通过 * 寻址,因为它们位于另一个命名空间中。

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

如果名称空间未知,这可能只是方便或特别有用。在这种情况下,好的副作用是,如果命名空间以这种方式标记,则来自另一个命名空间的节点不会获得注释——这在我们的例子中是不需要的。

于 2010-04-30T14:27:01.557 回答