XSL-именованный параметр with-param с использованием apply-templates - PullRequest
17 голосов
/ 19 ноября 2010

Мои вопросы находятся внизу этого поста, если вы хотите прочитать их до полного объяснения.

Я конвертирую XML-документ в симпатичную веб-страницу, используя XSL, и у меня возникают проблемы с правильной передачей переменной. У меня есть много xsl:template определенных, и мне нужно передать определенный параметр только одному из них. Я надеялся, что смогу передать именованный параметр, который предположительно будет отправлен всем xsl:template, но будет использоваться только одним и игнорироваться другими. Однако, пытаясь проверить это для себя (и моего ограниченного понимания XSL), я не смог пройти параметр вообще, не говоря уже о тестировании, если оно случайно мешало другим xsl:template s.

Ниже приведен упрощенный пример кода ( напечатан для этого вопроса, он может содержать опечатку или две ). У меня есть много разных xsl:template, определенных для работы с узлами в XML, и до сих пор все работало нормально. Похоже, что при добавлении параметра к этим шаблонам у меня возникают проблемы.

XML-файл:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<wrapperNode>
  <testNode>
    <subNode/>
  </testNode>
</wrapperNode>

main.xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="test.xsl"/>
<xsl:output method="html" indent="yes"/>

<xsl:template match="/">

<html>
  <body>
      <xsl:apply-templates>
        <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param>
      </xsl:apply-templates>
  </body>
</html>

</xsl:template>
</xsl:stylesheet>

test.xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="testNode">
  <xsl:param name="testParam" />
  TEST1
  <xsl:value-of select="$testParam" />
  TEST2
</xsl:template>
</xsl:stylesheet>

Вывод (фактический):

TEST1 TEST2

Вывод (ожидаемый / желаемый):

TEST1 TEST_PARAMETER TEST2

Мои вопросы по этому поводу:

  1. Можно ли отправить имя параметр для всех моих xsl:template с использованием xsl:apply-templates с xsl:with-param, но выберите это значение конкретно на name= в пределах фактический шаблон, чтобы он мог явно использоваться в одном шаблон и игнорируется всеми остальными (даже если бы я хотел добавить другое, по-разному, параметры для другие шаблоны позже)?

  2. Что я делаю не так с моим текущим примером кода, который, кажется, не получает параметр вообще?

  3. Есть ли лучший способ сделать это?

Редактировать: Я хочу прояснить, что из-за другого вывода в шаблоне test.xsl: testNode я точно знаю, что он IS успешно вызывается. Это ТОЛЬКО часть параметра, которая не работает. Я не хочу тратить время на то, чтобы понять, почему этот шаблон не вызывается. Это.

Обновление: В ответ на ответы, которые я первоначально получил, в которых указывалось, что приведенный мною пример был не совсем верным (моя ошибка) и не очень ясно показал проблему (т. Е. Что правильный шаблон вызывается , но только параметр, кажется, не работает), я заменил примеры на гораздо лучшие. Этот пример более четко показывает, что шаблон testNode успешно вызывается, но этот параметр, похоже, не передан. Я проверял это много раз, до и после рассмотрения предыдущих ответов на этот вопрос. Я абсолютно в замешательстве, так как все кажется правильным из того, что я читал в другом месте и что люди предложили до сих пор.

Ответы [ 2 ]

27 голосов
/ 19 ноября 2010

Мои вопросы по этому поводу:

  1. Можно ли отправить именованный параметр всем моим xsl: шаблонам, используя xsl: apply-templates с xsl: with-param, но выберите это значение специально по имени = в фактическом шаблоне, чтобы его можно было явно использовать в одном шаблоне и игнорировать все остальные (даже если позже я хотел добавить другие параметры с другими именами для других шаблонов)?

Да .В XSLT 2.0 можно использовать так называемые «параметры туннеля», но в XSLT 1.0 это способ , чтобы некоторые параметры достигли некоторого удаленного шаблона в цепочке.

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

.2.Что я делаю не так с моим текущим примером кода, который, кажется, не получает параметр вообще?

Причина в коде, который вы нам не показали ,Или, может быть, исходный XML-документ, который у вас есть в вашем реальном деле, отличается от того, который представлен здесь.Я запустил предоставленный код и вообще не смог воспроизвести проблему - получен желаемый результат.

Я предполагаю, что перед шаблоном, который соответствует testNode, выбран какой-то другой шаблон. Этот шаблон ничего не знает о переданном параметре и не передает его шаблонам, которые он, в свою очередь, применяет.Таким образом, параметр вообще не передается в шаблон, соответствующий testNode.

. Я предполагаю, что если вы замените:

  <xsl:apply-templates> 
    <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> 
  </xsl:apply-templates> 

на

  <xsl:apply-templates select="testNode"> 
    <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> 
  </xsl:apply-templates> 

, выможет получить желаемый результат.

Кроме того, вы можете отследить с помощью отладчика XSLT (например, в Visual Studio) и посмотреть, какой именно шаблон выбран.

.3.Есть ли лучший способ сделать это?

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

Наконец , вот код, который я запустил, который не может воспроизвести вашу проблему:

Таблица стилей XSLT :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>

 <xsl:template match="/">
      This is text1
      <xsl:apply-templates>
        <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param>
      </xsl:apply-templates>
      This is text2
 </xsl:template>

 <xsl:template match="testNode">
  <xsl:param name="testParam" />
  <xsl:value-of select="$testParam" />
 </xsl:template>
</xsl:stylesheet>

XML-документ :

<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<testNode>
  <subNode/>
</testNode>

Результат :

  This is text1
  TEST_PARAMETER
  This is text2

ОБНОВЛЕНИЕ:

ОП предоставил более точную информациючто доказывает мое предположение.

Теперь очевидно, что проблема вызвана тем, что для wrapperNode был выбран встроенный шаблон XSLT для узла элемента.Этот шаблон, естественно, не знает ни о каких параметрах и не использует параметр testParam, а также не пропускает этот параметр.Таким образом, <xsl:apply-templates/> во встроенном шаблоне приводит к тому, что соответствующий шаблон testNode выбирается без передачи ему какого-либо параметра.Это объясняет сообщаемое поведение / результат.

Решение : Решение состоит в том, чтобы указать шаблон, соответствующий wrapperNode, который принимает параметр с именем testParam и передает его при применении шаблонов:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="html" indent="yes"/>

 <xsl:template match="/">
  <html>
    <body>
        <xsl:apply-templates>
          <xsl:with-param name="testParam" select="'TEST_PARAMETER'"/>
        </xsl:apply-templates>
    </body>
  </html>
 </xsl:template>

 <xsl:template match="testNode">
  <xsl:param name="testParam" />
  TEST1
  <xsl:value-of select="$testParam" />
  TEST2
 </xsl:template>

 <xsl:template match="wrapperNode">
  <xsl:param name="testParam" />

  <xsl:apply-templates>
   <xsl:with-param name="testParam" select="$testParam"/>
  </xsl:apply-templates>
 </xsl:template>
</xsl:stylesheet>

Теперь, когда это преобразование применяется к предоставленному XML-документу, получается ожидаемый результат :

<html>
<body>
  TEST1
  TEST_PARAMETER
  TEST2
 </body>
</html>
1 голос
/ 19 ноября 2010

Ваши теги <html> и <body> не могут появляться там, где они находятся в таблице стилей XSL. Когда я удаляю их и закрывающие теги и запускаю это в Oxygen / XML, я получаю ваш «желаемый» вывод. Я думаю, что вы хотите поместить эти теги ВНУТРИ шаблона верхнего уровня, и в этом случае он будет генерировать вывод в тегах html и body.

Какой механизм XSLT вы использовали, который не жаловался на неверную таблицу стилей?

...