2010-08-19 7 views
9

Tengo un documento XML que estoy sujeto a un XSLT. La estructura es similar a:xsl: aplicar plantilla a solo nodos con valor de atributo específico

<root> 
    <item value="1"> 
    <object/> 
    </item> 
    <item value="2" /> 
    <object/> 
    </item> 
</root> 

Mi objetivo es terminar con un XML transformado similar a:

<root> 
<parent> 
    <object-one value-one="1"/> 
</parent> 
<parent> 
    <object-two value-two="2"/> 
</parent> 
</root> 

Mi XSLT es similar a:

<xsl:apply-templates select="object" /> 


<xsl:template match="object"> 
    <xsl:call-template name="1" /> 
    <xsl:call-template name="2" /> 
</xsl:template> 

<xsl:template name="1" match="object[item/@value = '1'"> 
    <xsl:element name="object-one" namespace="http://something.org"> 
    <xsl:attribute name="_Description"> 
     <xsl:value-of select="@_Type"/> 
    </xsl:attribute> 
    <xsl:attribute name="_Type"> 
     <xsl:value-of select="@_Amount"/> 
    </xsl:attribute> 
    </xsl:element> 
</xsl:template> 

<xsl:template name="2" match="object[item/@value = '2'"> 
    <xsl:element name="object-two" namespace="http://something.org"> 
    <xsl:attribute name="OriginalAmount"> 
     <xsl:value-of select="@_Amount"/> 
    </xsl:attribute> 
    </xsl:element> 
</xsl:template> 

El problema es la todos los nodos de elementos tienen la misma plantilla aplicada. ¿Cómo puedo aplicar una plantilla solo a nodos específicos?

Respuesta

7

EDITAR: Ahora para diferentes muestras de entrada (corregido para bien formada):

<root> 
    <item value="1"> 
     <object/> 
    </item> 
    <item value="2" > 
     <object/> 
    </item> 
</root> 

Esta hoja de estilo:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:num="number" extension-element-prefixes="num"> 
    <num:num>one</num:num> 
    <num:num>two</num:num> 
    <xsl:template match="root"> 
     <xsl:copy> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="item"> 
     <parent> 
      <xsl:apply-templates/> 
     </parent> 
    </xsl:template> 
    <xsl:template match="object"> 
     <xsl:variable name="vTextNumber" select="document('')/*/num:*[number(current()/../@value)]"/> 
     <xsl:element name="object-{$vTextNumber}"> 
      <xsl:attribute name="value-{$vTextNumber}"> 
       <xsl:value-of select="../@value"/> 
      </xsl:attribute> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

Salida:

<root> 
    <parent> 
     <object-one value-one="1" /> 
    </parent> 
    <parent> 
     <object-two value-two="2" /> 
    </parent> 
</root> 

EDIT 2: Ahora, lo que está mal dentro de su fragmento de hoja de estilo? Bueno, parece que no sabes cómo el procesador resuelve las reglas de plantilla aplicadas, también la navegación XPath.

En primer lugar, este object[item/@value = '1'] sólo coincidirá con este tipo de entrada

<object> 
    <item value="1"/> 
</object> 

segundo lugar, considerar esto tres reglas

1 -

<xsl:template match="object"> 
</xsl:template> 

2 -

<xsl:template name="1" match="object[../@value = '1']"> 
</xsl:template> 

3 -

<xsl:template name="2" match="object[../@value = '2']"> 
</xsl:template> 

Con su última entrada proporcionada, primero object elemento (en el orden del documento) coincidirá con las reglas 1 y 2, y entonces el procesador resolvería aplicar la regla 2. ¿Por qué? De http://www.w3.org/TR/xslt#conflict

A continuación, toda la plantilla a juego reglas que tienen menor prioridad que la regla plantilla a juego o las reglas con el prioridad más alta se eliminan de consideración. La prioridad de una regla de plantilla se especifica mediante el atributo de prioridad en la regla de la plantilla . El valor de esto debe ser un número real (positivo o negativo), que coincida con el Número de producción con un signo de menos principal (-).La prioridad predeterminado se calcula como sigue:

  • Si el patrón contiene múltiples alternativas separadas por |, entonces
    es tratado de forma equivalente a un conjunto de reglas de plantilla, una para cada
    alternativa.
  • Si el patrón tiene la forma de un QName precedido por un ChildOrAttributeAxisSpecifier
    o tiene la forma instrucción de procesamiento (literal)
    precedido por un ChildOrAttributeAxisSpecifier, a continuación, la prioridad es 0.
  • Si el patrón tiene la forma NCName: * precedido por
    ChildOrAttributeAxisSpecifier, la prioridad es -0.25.
  • De lo contrario, si el patrón consiste en solo un NodeTest precedido por un ChildOrAttributeAxisSpecifier, entonces la prioridad es -0.5.
  • De lo contrario, la prioridad es 0.5.
+0

Intenté sus sugerencias, pero no pude obtener los resultados deseados. Sigue aplicando solo una de las dos plantillas a cada , mientras que el objetivo es aplicar ambas plantillas, pero solo cuando la condición coincida. Consulte mi pregunta revisada con un código más preciso. – alan

+0

El principal problema que tengo es que el valor que estoy probando pertenece al padre del nodo al que le estoy aplicando la plantilla. – alan

+0

@alan: 'Probé tus sugerencias, pero no pude obtener los resultados deseados. ¡Bien, ** has cambiado la entrada y la salida deseada **! La mejor práctica sería hacer otra pregunta. De lo contrario, debería agregar esas noticias a su pregunta, pero no reemplazarlas. Echa un vistazo a mi edición. Si hay algo que no está claro para usted desde mi propia hoja de estilo, solo pregunte específicamente. –

0

Tal vez usted puede hacer sus partidos más específico:

<xsl:template name="item1" match="item[@value=1]"> 
    <xsl:element name="item" namespace="http://something.org"> 
     <xsl:attribute name="_Description"> 
      <xsl:value-of select="@_Type"/> 
     </xsl:attribute> 
     <xsl:attribute name="_Type"> 
      <xsl:value-of select="@_Amount"/> 
     </xsl:attribute> 
    </xsl:element> 
</xsl:template> 

<xsl:template name="item2" match="item[@value=2]"> 
    <xsl:element name="item2_item" namespace="http://something.org"> 
     <xsl:attribute name="OriginalAmount"> 
      <xsl:value-of select="@_Amount"/> 
     </xsl:attribute> 
    </xsl:element> 
</xsl:template> 
+0

Gracias por su sugerencia, he intentado poner en práctica sus sugerencias pero todavía consigue solamente una plantilla aplicada a todos los nodos . – alan

Cuestiones relacionadas