Почему дочерний или собственный :: не разрешен в шаблоне? - PullRequest
0 голосов
/ 10 ноября 2011

Предположим, у меня есть следующий XML (который представляет собой схему аннотации TEI в HTML):

<p>(See, for example, <bibl type="journal" xmlns="http://www.tei-c.org/ns/1.0"><author>Greger IH, et al.</author> <date>2007</date>, <title>Trends Neurosci.</title> <biblScope type="vol">30</biblScope> (<biblScope type="issue">8</biblScope>): <biblScope type="pp">407-16</biblScope></bibl>).</p>

Теперь я хочу скопировать всю аннотациюузлы как есть в результирующий XHTML, но только переименовывают <title> в <bibTitle> (так как <title> допускается только в <head>), поэтому я использовал следующее преобразование:

<xsl:template match="tei:bibl/descendant-or-self::*">
    <xsl:variable name="nodeName">
        <xsl:choose>
            <xsl:when test="name() = 'title'">bibTitle</xsl:when>
            <xsl:otherwise><xsl:value-of select="name()" /></xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <!-- Changing of the namespace occurs here, but we don't care -->
    <xsl:element name="{$nodeName}">
        <xsl:copy-of select="@*" />
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="p/text()|tei:bibl//text()">
    <xsl:copy-of select="." />
</xsl:template>

Однако он не компилируется и прерывается со следующей ошибкой:

Only child:: and attribute:: axes are allowed in match patterns! Offending axes = descendant-or-self

Когда я изменяю правило сопоставления на <xsl:template match="tei:bibl|tei:bibl//*">, оно начинает работать как положено.Но это должно быть идентично descendant-or-self::*, верно?Я достиг здесь ограничения по реализации трансформатора?

Сначала я проверил с внутренним трансформатором Mozilla 3.5, затем с Xalan 2.7.1 - тот же отрицательный результат.

Ответы [ 4 ]

2 голосов
/ 10 ноября 2011

Это ограничение действительно только для любого шага местоположения в шаблоне совпадения шаблона .Это предусмотрено (предписано спецификациями W3C XSLT 1.0 и XSLT 2.0 ) - для обеспечения эффективной обработки XSLT.

Примечание : можно свободно использовать любую ось (включая descending-or-self::) в предикатах, следующих за любым шагом местоположения.

Обновление :

Вот краткий, полный пример использования оси descendant-or-self:: в атрибуте match xsl:template:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="num[descendant-or-self::num > 5]"/>
</xsl:stylesheet>

, когда это преобразование применяется к следующему XMLdocument :

<nums>
 <num>1</num>
 <num>2</num>
 <num>3</num>
 <num>4</num>
 <num>5</num>
 <num>6</num>
 <num>7</num>
 <num>8</num>
 <num>9</num>
 <num>10</num>
</nums>

требуемый результат: удаляются любые num элементы со значением> = 5:

<nums>
  <num>1</num>
  <num>2</num>
  <num>3</num>
  <num>4</num>
  <num>5</num>
</nums>
1 голос
/ 31 января 2012

Вот случай, когда этого недостаточно:

<a>
  <b>
    <c>
      <c>
        <c/>
      </c>
    </c>
  </b>
  <c>
    <c>
      <c/>
    </c>
  </c>
</a>

Теперь я хочу соответствовать только:

*[self::a or self::b][p(.)]/c/descendent-or-self::c

то есть, если предикат p (.) Истинен для a, я хочу a / c, a / c / c, a / c / c / c, и если это верно для b, я хочу b / c, b / c / c, и b / c / c / c.

Но я не хочу a / b / c, a / b / c / c и т. Д. Только потому, что предикат совпадает с a, а не с b.

Если я сделаю шаблон совпадения:

*[self::a or self::b][p(.)]//c 

тогда я сопоставляю их всех, чего не хочу.

Так что я должен сделать это в скобках назад:

c[ancestor-or-self::c/parent::*[self::a or self::b][p(.)]]

Мне кажется, я просто убедил себя, что это ограничение не является логическим ограничением, однако я считаю оправдание не допускать правильных шагов оси в шаблонах совпадений довольно неубедительным, потому что, когда мне это нужно, мне нужно это, кто заботится, если это не так быстро, как если бы я использовал более простые выражения.

1 голос
/ 10 ноября 2011

Вот способ, которым вы можете переписать шаблон в эквивалентный, который не повторяет упоминание tei:bibl:

<xsl:template match="*[ancestor-or-self::tei:bibl]">

Относительно того, почему существует ограничение, общий ответ - да, для производительности. Возможно, ограничения чрезмерно консервативны, потому что, как вы указали, переписывание потомка или самого себя в этом случае тривиально.

Меня регулярно раздражает это ограничение (которое вы можете использовать //, но не потомок).

1 голос
/ 10 ноября 2011

Это жесткое требование для спецификации :

Хотя шаблоны не должны использовать ось «потомок или само», шаблоны могут использовать оператор //, а также/ оператор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...