2010-04-29 70 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