2010-04-29 15 views
5

Grüße!XSLT Document Funktion gibt leeres Ergebnis auf Maven POM zurück

Ich möchte einige Eigenschaften aus verschiedenen Maven POMs in einem XSLT über die Dokumentfunktion extrahieren. Das Skript selbst funktioniert gut, aber die Dokumentfunktion gibt ein leeres Ergebnis für das POM zurück, solange ich die xmlns = "http://maven.apache.org/POM/4.0.0" im Projekt-Tag habe. Wenn ich es entferne, funktioniert alles gut.

Eine Idee, wie dies funktioniert, während das xmlns-Attribut dort bleibt, wo es hingehört oder warum das nicht mit dem Attribut funktioniert?

Hier kommt der relevante Teil meiner 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> 

Und der Vollständigkeit halber, einen POM-Extrakt mit dem "schlechten" Attribut:

<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

Gute Frage (+1). Siehe meine Antwort für eine Erklärung des Problems und für die am häufigsten verwendete Lösung. :) –

Antwort

10

Ihr Problem besteht darin, dass der POM-Extrakt den Standardnamespace verwendet. Dies bedeutet, dass die Elemente, obwohl sie nicht voreingestellt sind, im "http://maven.apache.org/POM/4.0.0" sind - nicht im "no namespace".

jedoch in diesem XPath-Ausdruck, in dem XSLT-Code:

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

die Namen project und properties sind ohne Präfix. XPath behandelt immer Namen ohne Präfix als "kein Namespace". Daher werden keine solchen Elemente gefunden und kein Knoten ausgewählt.

Lösung: eine Namespace-Definition Ihrer <xsl:stylesheet> hinzufügen, können sagen:

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

Dann Elementnamen in allen Ausdrücken Referenzierung POM Knoten von someElement zu p:someElement umschreiben. Zum Beispiel:

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

Danke Dimitre - das funktioniert! Im Moment gibt diese Lösung mir xmlns: pom = "..." in jedem Element, das ich vom Dokumentfunktionsaufruf bekomme, aber ich hoffe, einen Weg zu finden, um das loszuwerden, vielleicht indem ich vorher die Deklaration im Zieldokument zur Verfügung stelle. – Jan

+0

@Jan: Fügen Sie einfach das '' das folgende Attribut hinzu: 'exclude-result-prefixes =" pom "' –

+0

Ah! Das ist eine nette Ergänzung - danke. Ich habe auch eine allgemeine Lösung gefunden, die für meine speziellen Bedürfnisse nützlich ist (siehe meine Antwort). – Jan

3

Dies ist ein Namespace ist Problem. Die xmlns="http://maven.apache.org/POM/4.0.0" im Quelldokument bedeutet, dass alle Elemente standardmäßig in den Namensraum "http://maven.apache.org/POM/4.0.0" im XML-Dokument eingefügt werden.

Wenn Sie sie in Ihrer XSLT abrufen möchten, müssen Sie diesen Namespace in Ihrem XSLT deklarieren (mit oder ohne zu verwendendem Präfix) und diesen Namespace dann bei der Auswahl Ihrer Elemente verwenden.

Zum Beispiel, ich vermute, dass die Vorlage in Ihrem Beispiel ein "ABC" -Element in Ihrem POM übereinstimmen soll, ja? Versuchen Sie, einen Namespace-Deklaration in Ihrem xsl fügte hinzu: „Ich möchte hinzufügen‚pom‘als Präfix, das die‚http://maven.apache.org/POM/4.0.0‘Namespace in diesem Dokument identifiziert“ Sheet, z.B .:

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

, die mit dem XSL sagt

Dann, wenn Elemente oder passende Vorlagen auszuwählen, verwenden Sie diesen Präfix, zB:

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

Oder versuchen Sie es ohne die Präfixe von Ihrem Stylesheet mit dem POM-Namespace als Standard erklärt, so etwas wie:

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

Danke! Leider funktioniert der "globale Ansatz" bei mir nicht - anscheinend, weil ich auch Tags aus anderen Namensräumen habe. Vielleicht war meine Frage nicht präzise genug - die ABCs sind in einem anderen Namensraum. Der Ansatz mit Präfix funktioniert für mich, wie Dimitre unten vorgeschlagen hat. – Jan

+0

@Matt: Wenn Sie bei der Auswahl von Elementen mit XPath einen Standardnamespace verwenden möchten, müssen Sie 'xpath-default-namespace' (unterstützt in XSLT 2.0 oder höher) verwenden, wie in http://www.w3.org/TR beschrieben/xslt20/# ohne Präfix-qnamen. Wenn der Standard-Namespace mit 'xmlns =" ​​... "festgelegt wird, wird nur der Standard-Namespace von XML-Literalen im Stylesheet konfiguriert, XPath-Ausdrücke sind nicht betroffen. – markusk

+0

@markusk Danke für die Klarstellung; Ich habe noch keinen xpath-default-namespace benutzt, sicher, dass das irgendwann in meiner Zukunft nützlich sein wird! –

1

Knoten kann (bei Verwendung von XSLT 2.0 +) auch über * angesprochen werden, weil sie in einem anderen Namensraum liegen.

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

Dies kann nur convienent oder besonders nützlich sein, wenn der Namespace unbekannt ist. In diesem Fall ist der nette Nebeneffekt, dass, wenn der Namespace auf diese Weise markiert ist, die Knoten aus dem anderen Namespace keine Annotation bekommen - was in unserem Fall nicht erwünscht ist.

+1

@Jan: Die Syntax '*: name' wird nur in XPath 2.0 unterstützt. –

+0

@Jan: Beachten Sie auch, dass Sie 'xpath-default-namespace' verwenden können, wenn Sie XSLT 2.0 oder höher verwenden, wie in http://www.w3.org/TR/xslt20/#unprefixed-qnames beschrieben. – markusk

+0

10 @Dimitre: Sicher - Entschuldigung, ich habe vergessen, dieses Detail hinzuzufügen (mit dem). – Jan