xsl: apply-template только для узлов с определенным значением атрибута - PullRequest
10 голосов
/ 20 августа 2010

У меня есть документ XML, который я подвергаю XSLT. Структура похожа на:

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

Моя цель - получить преобразованный XML, похожий на:

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

Мой XSLT похож на:

<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>

Проблема в том, что ко всем узлам элемента применяется один и тот же шаблон. Как я могу применить шаблон только к определенным узлам?

Ответы [ 2 ]

9 голосов
/ 20 августа 2010

РЕДАКТИРОВАТЬ : теперь для другой входной выборки (с поправкой на правильную форму):

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

Эта таблица стилей:

<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>

Выход:

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

РЕДАКТИРОВАТЬ 2 : Теперь, что не так в вашем фрагменте таблицы стилей? Похоже, вы не знаете, как процессор разрешает применение правил шаблонов, а также навигацию XPath.

Во-первых, этот object[item/@value = '1'] будет соответствовать только этому виду ввода

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

Во-вторых, рассмотрим эти три правила

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> 

С вашим последним предоставленным вводом первый элемент object (в порядке документа) будет соответствовать правилам 1 и 2, а затем процессор решит применить правило 2. Почему? От http://www.w3.org/TR/xslt#conflict

Далее, все соответствующие шаблонные правила, которые иметь более низкий приоритет, чем соответствующий шаблонное правило или правила с высший приоритет исключаются из рассмотрение. Приоритет шаблонное правило определяется атрибут приоритета в шаблоне править. Значение этого должно быть реальным число (положительное или отрицательное), соответствие производственного номера с необязательный ведущий знак минус (-). приоритет по умолчанию вычисляется как следующим образом:

  • Если шаблон содержит несколько альтернатив, разделенных |, то он
    обрабатывается эквивалентно набору шаблонных правил, по одному для каждого
    альтернатива.
  • Если шаблон имеет форму QName, перед которым стоит
    ChildOrAttributeAxisSpecifier или имеет инструкцию обработки формы (литерал)
    ему предшествует ChildOrAttributeAxisSpecifier, тогда приоритет равен 0.
  • Если шаблон имеет форму NCName: * ему предшествует
    ChildOrAttributeAxisSpecifier, тогда приоритет равен -0.25.
  • В противном случае, если шаблон состоит только из NodeTest предшествует ChildOrAttributeAxisSpecifier, затем приоритет -0,5.
  • В противном случае приоритет равен 0,5.
0 голосов
/ 20 августа 2010

Возможно, вы можете сделать свои матчи более конкретными:

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...