XSL: влияет на одни и те же узлы с более чем одним шаблоном - PullRequest
1 голос
/ 28 октября 2011

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

Иногда, однако, вы хотите воздействовать на внешний узел одним шаблоном, а затем повлиять на своих детей / потомков с другим шаблоном.Было бы целесообразно следующее?Его цель - добавить атрибут 'attr' к каждому узлу.

Исходный XML: привет!

XSL:

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

    <xsl:template match='child'>
        <child>
            <xsl:attribute name='attr'>val</xsl:attribute>
            <xsl:apply-templates select='./*' />
        </child>
    </xsl:template>

    <xsl:template match='greatgrandchild'>
        <greatgrandchild>
            <xsl:attribute name='attr'>val</xsl:attribute>
            <xsl:value-of select='.' />
        </greatgrandchild>
    </xsl:template>

</xsl:stylesheet>

Я на правильных линиях?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 28 октября 2011

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

Ни одно из этих утверждений не соответствует действительности . Различные шаблоны могут быть выбраны для выполнения на одном и том же узле - все это зависит от инструкций <xsl:apply-templates>, которые приводят к выбору конкретного шаблона для выполнения. Способ применения и выбора шаблонов очень велик, например, приоритет импорта, приоритет, режимы и т. Д.

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

Иногда, однако, вы хотите воздействовать на внешний узел одним шаблоном, затем воздействуйте на своих потомков / потомков другим шаблоном. Будет ли Следующее будет целесообразным способом обойти это? Его цель - добавить атрибут "attr" для каждого узла.

Это тривиально достигается с помощью самого основного шаблона проектирования XSLT - переопределения правила идентификации :

<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="*">
  <xsl:variable name="val" select="count(ancestor::node())"/>
  <xsl:copy>
    <xsl:attribute name="depth">
      <xsl:value-of select="$val"/>
    </xsl:attribute>
      <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML (исправлено, чтобы оно было правильно сформировано):

<root>
    <child>
        <grandchild>
            <greatgrandchild>hello! </greatgrandchild>
        </grandchild>
    </child>
</root>

копирует каждый узел и добавляет атрибут depth к каждому элементу. Значением добавленного атрибута является «глубина» элемента :

<root depth="1">
   <child depth="2">
      <grandchild depth="3">
         <greatgrandchild depth="4">hello! </greatgrandchild>
      </grandchild>
   </child>
</root>
0 голосов
/ 28 октября 2011

Честно говоря, обрабатывается ли узел, полностью зависит от ваших шаблонов и встроенных шаблонов (которые могут быть переопределены).Если шаблон для узлов элемента foo имеет значение <xsl:apply-templates/>, то дочерние узлы обрабатываются, если он выполняет <xsl:apply-templates select="ancestor::*"/>, то обрабатываются его элементы-предки, просто для того, чтобы привести два примера.Конечно, если вы напишите шаблон для определенного элемента, который не использует apply-templates для дальнейшей обработки, то обработка останавливается.

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

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

<xsl:template match="*">
  <xsl:copy>
   <xsl:apply-templates select="@*"/>
   <xsl:attribute name="attr">val</xsl:attribute>
   <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

чтобы шаблон преобразования идентификаторов плюс один для узлов элементов добавили новый атрибут.

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