Почему шаблон XSLT не применяется? - PullRequest
1 голос
/ 27 марта 2019

У меня есть некоторый XML, который представляет две альтернативные версии некоторого текста, и я использую XSLT для выполнения модификации, которая выбирает ту или иную версию.Кроме того, одна альтернатива также содержит заполнитель, который должен быть заменен другим битом текста.

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

Фактический код использует lxml python, но я в основном тестировал XSLT в notepad ++ сXML-плагин.Плагин использует libxml2 и libxslt, например lxml, поэтому они не должны отличаться.

Я пробовал добавлять различные версии <xsl:apply-template /> в шаблон 2, но ничего не приводит к тому, что заполнитель получает значение, которое яОжидайте

Ниже приведена очень урезанная версия XML:

<sn:text xmlns:sn="http://some.namespace" xmlns="http://www.w3.org/1999/xhtml">
  <p>
    <sn:alts sn:id="alts_1">
      <sn:alt sn:id="alt_1">start 1</sn:alt>
      <sn:alt sn:id="alt_2">
        <sn:placeholder sn:id="p_1"/> start 2</sn:alt>
    </sn:alts> blah blah blah...</p>
</sn:text>

И вот сгенерированный XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:sn="http://some.namespace">
  <!--template 1-->
  <xsl:template match="sn:placeholder[@sn:id='p_1']">XYZ</xsl:template>
  <!--template 2-->
  <xsl:template match="sn:alts[@sn:id='alts_1']">
    <xsl:value-of select="sn:alt[@sn:id='alt_2']" />
  </xsl:template>
  <!--identity transform-->
  <xsl:template match="*">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="@*|text()|comment()|processing-instruction">
    <xsl:copy-of select="."/>
  </xsl:template>
</xsl:stylesheet>

В результате яожидание должно быть примерно таким:

<sn:text xmlns:sn="http://some.namespace" xmlns="http://www.w3.org/1999/xhtml">
  <p>XYZ start 2 blah blah blah...</p>
</sn:text>

Вместо этого заполнитель не заменяется на "XYZ", а полностью исключается:

<sn:text xmlns:sn="http://some.namespace" xmlns="http://www.w3.org/1999/xhtml">
  <p> start 2 blah blah blah...</p>
</sn:text>

Обновление

Спасибо за указатели.В конце концов, это было совершенно очевидно:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:sn="http://some.namespace">
  <xsl:strip-space elements="*"/>
  <xsl:output method="xml" indent="yes" />
  <!--template 1-->
  <xsl:template match="sn:placeholder[@sn:id='p_1']">XYZ</xsl:template>
  <!--template 2-->
  <xsl:template match="sn:alts[@sn:id='alts_1']">
    <xsl:apply-templates select="sn:alt/sn:placeholder"/>
    <xsl:value-of select="sn:alt[@sn:id='alt_1']" />
  </xsl:template>
  <!--identity transform-->
  <xsl:template match="*">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="@*|text()|comment()|processing-instruction()">
    <xsl:copy-of select="."/>
  </xsl:template>
</xsl:stylesheet>

Ответы [ 3 ]

1 голос
/ 27 марта 2019

Шаблон не применяется, потому что вы никогда не выбираете узел, которому он соответствует, в инструкции xsl:apply-templates. Это потому, что ваш match="sn:alts" не применяет шаблоны к своим дочерним элементам.

Кстати, processing-instruction должно быть processing-instruction().

0 голосов
/ 27 марта 2019

Логика, которую вы пытаетесь реализовать следующим образом:

  1. Если «alt_2» существует, выведите его (с модификацией для заполнителя) и игнорируйте «alt_1»
  2. В противном случае выведите «alt_1»

В этом случае попробуйте этот XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:sn="http://some.namespace">

  <!--template 1-->
  <xsl:template match="sn:placeholder[@sn:id='p_1']">XYZ</xsl:template>

  <!--template 2-->
  <xsl:template match="sn:alts[sn:alt[@sn:id='alt_2']]/sn:alt[@sn:id='alt_1']" />

  <xsl:template match="sn:*">
      <xsl:apply-templates />
  </xsl:template>

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

  <xsl:template match="@*|text()|comment()|processing-instruction">
    <xsl:copy-of select="."/>
  </xsl:template>
</xsl:stylesheet>

См. http://xsltfiddle.liberty -development.net / ncdD7mo

0 голосов
/ 27 марта 2019
<xsl:stylesheet version = "2.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:sn="http://some.namespace" xmlns:html="http://www.w3.org/1999/xhtml">
    <xsl:strip-space elements="*"/>
    <xsl:output method = "xml" indent = "yes" />
    <xsl:template match="sn:text">
        <xsl:copy>
        <p>
        <xsl:apply-templates select="html:p/sn:alts/sn:alt[@sn:id = 'alt_2']"/>
        <xsl:apply-templates select="html:p/text()"/>
        </p>
   </xsl:copy>
    </xsl:template>

    <xsl:template match="sn:alt[@sn:id = 'alt_2']">
        <xsl:text>xyz </xsl:text><xsl:value-of select="."/><xsl:text> </xsl:text>
    </xsl:template>

</xsl:stylesheet>
You may try it.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...