2010-04-29 9 views
5

¡Saludos!XSLT La función de documento devuelve el resultado vacío en Maven POM

Quiero extraer algunas propiedades de diferentes POM Maven en un XSLT a través de la función de documento. La secuencia de comandos en sí funciona bien, pero la función de documento devuelve un resultado vacío para el POM, siempre que tenga el xmlns = "http://maven.apache.org/POM/4.0.0" en la etiqueta del proyecto. Si lo elimino, todo funciona bien.

¿Alguna idea de cómo hacer que esto funcione mientras se deja el atributo xmlns a donde pertenece o por qué esto no funciona con el atributo en su lugar?

Aquí viene la parte relevante de mi 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> 

y como complemento, un extracto de POM con el "malo" de atributos:

<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

Buena pregunta (+1). Consulte mi respuesta para obtener una explicación del problema y la solución más utilizada. :) –

Respuesta

10

Su problema es que el extracto de POM utiliza el espacio de nombres predeterminado. Esto significa que los elementos, aunque no estén prefijados, se encuentran en "http://maven.apache.org/POM/4.0.0", no en "sin espacio de nombres".

Sin embargo, en esta expresión XPath, en el código XSLT:

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

los nombres project y properties son sin prefijo. XPath siempre trata los nombres no prefijados como pertenecientes a "sin espacio de nombres". Por lo tanto, no se encuentran tales elementos y no se selecciona ningún nodo.

Solución: Añadir una definición de espacio de nombres a su <xsl:stylesheet>, le dicen:

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

vuelva a grabar los nombres de elementos en cualquier expresiones que hacen referencia a nodos de POM someElement a p:someElement. Por ejemplo:

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

Gracias Dimitre - ¡esto funciona! En este momento, esta solución me da xmlns: pom = "..." en cada elemento que obtengo de la llamada a la función del documento, pero espero encontrar alguna manera de deshacerme de eso, quizás proporcionando la declaración en el documento de destino antes. – Jan

+0

@Jan: simplemente agregue a '' el siguiente atributo: 'exclude-result-prefixes =" pom "' –

+0

¡Ah! Es una buena adición, gracias. También encontré una solución general que es útil para mi necesidad especial (ver mi respuesta). – Jan

3

Este es un espacio de nombres problema. El xmlns="http://maven.apache.org/POM/4.0.0" en el documento fuente significa que todos los elementos se colocan por defecto en el espacio de nombres "http://maven.apache.org/POM/4.0.0" en el documento XML.

Si desea obtenerlos en su xslt, necesita declarar ese espacio de nombres en su xslt (con o sin un prefijo para usar) y luego usar ese espacio de nombres cuando seleccione sus elementos.

Por ejemplo, supongo que la plantilla de su ejemplo debe coincidir con un elemento "abcs" en su POM, ¿sí? Trate de añadir una declaración de espacio de nombres en su xsl: stylesheet, por ejemplo .:

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

que dice que el XSL "Quiero añadir 'pom' como prefijo que identifica el 'http://maven.apache.org/POM/4.0.0' espacio de nombres en este documento."

A continuación, la hora de seleccionar los elementos o plantillas de juego, utilice ese prefijo, por ejemplo:

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

o intente hacerlo sin los prefijos declarando su hoja de estilos con el espacio de nombres POM como predeterminado, algo así como:

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

¡Gracias! Lamentablemente, el "enfoque global" no funciona para mí, aparentemente porque también tengo etiquetas de otros espacios de nombres. Tal vez mi pregunta no fue lo suficientemente precisa: los abcs están en otro espacio de nombres. Sin embargo, el enfoque por prefijo funciona para mí, como lo sugiere Dimitre a continuación. – Jan

+0

@Matt: si desea un espacio de nombre predeterminado al seleccionar elementos con XPath, debe usar 'xpath-default-namespace' (compatible con XSLT 2.0 o posterior), como se describe en http://www.w3.org/TR/xslt20/# unprefixed-qnames. Al configurar el espacio de nombre predeterminado con 'xmlns =" ​​... "' solo se configura el espacio de nombres predeterminado de los literales XML en la hoja de estilo, las expresiones XPath no se ven afectadas. – markusk

+0

@markusk Gracias por la aclaración; Todavía no he usado xpath-default-namespace, ¡seguro que será útil en algún momento de mi futuro! –

1

nodo puede (si se utiliza XSLT 2.0 +) también dirigirá, a través de * porque se encuentran en otro espacio de nombres.

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

Esto puede ser muy conveniente o especialmente útil si el espacio de nombres es desconocido. En este caso, el buen efecto secundario es que si el espacio de nombres está marcado de esta manera, los nodos del otro espacio de nombres no reciben una anotación, lo que no es necesario en nuestro caso.

+1

@ Jan: la sintaxis '*: name' solo se admite en XPath 2.0. –

+0

@ Jan: También tenga en cuenta que puede usar 'xpath-default-namespace' si está utilizando XSLT 2.0 o posterior, como se describe en http://www.w3.org/TR/xslt20/#unprefixed-qnames. – markusk

+0

@Dimitre: Claro, lo siento, olvidé agregar ese detalle (usando eso). – Jan