XSLT-документ с динамическим путем - PullRequest
0 голосов
/ 23 ноября 2011

У меня есть стандарт XSLT 1.0. У меня есть один динамический XML с сервера, который является довольно простым, и второй XML в качестве конфигурации. Основываясь на первом (который является динамическим), я должен подобрать правильную информацию об узлах из второго. Это первый документ:

<?xml version="1.0" encoding="UTF-8" ?>
<response>
    <response>SUCCESS</response>
    <responsedata>
        <hit>
            <url>http://domain.com/page.html</url>
            <id>2437</id>
            <title>Page title</title>
            <language>en</language>
            ...
            ...
        </hit>
    </responsedata>
</response>

Второй конфигурационный XML для нижнего колонтитула, заголовок разделен на языки. Примерно так:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <set id="local">
        <header>
            <en>
                <![CDATA[
<div id="header">
    <p>English code</p>
</div>
                ]]>
            </en>
            <fr>
                <![CDATA[
<div id="header">
    <p>French code</p>
</div>
                ]]>
            </fr>
        </header>
    </set>
</config>

Мне нужно подобрать правильный код, зависящий от языка, из второго XML. Я попробовал следующий код, и он не работает:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" omit-xml-declaration="yes" encoding="utf-8" indent="yes" doctype-system="about:legacy-compat" />
    <xsl:variable name="configuration" select="document('settings.xml')/config/set[@id='local']" />
    <xsl:variable name="lang" select="response/responsedata/hit/language" />

    <xsl:template name="getvalueofnode">
        <xsl:param name="path" />
        <xsl:param name="context" select="$configuration" />
        <xsl:choose>
            <xsl:when test="contains($path,'/')">
                <xsl:call-template name="getvalueofnode">
                    <xsl:with-param name="path"    
                        select="substring-after($path,'/')" />
                    <xsl:with-param name="context" 
                        select="$context/*[name()=substring-before($path,'/')]" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <p>value: <xsl:value-of select="$context/*[name()=$path]" disable-output-escaping="yes" /></p>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="/">
        <xsl:element name="html">
            <xsl:attribute name="lang"><xsl:value-of select="$lang" /></xsl:attribute>
            <xsl:element name="head">
                <xsl:attribute name="lang"><xsl:value-of select="$lang" /></xsl:attribute>
            </xsl:element>
            <xsl:element name="body">
                <xsl:attribute name="lang"><xsl:value-of select="$lang" /></xsl:attribute>
                <p>lang: <xsl:value-of select="$lang" /></p>
                <p>
                <xsl:call-template name="getvalueofnode">
                    <xsl:with-param name="path" select="concat('/header/',$lang)" />
                </xsl:call-template>
                </p>
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Если у кого-то есть какое-либо предложение или решение, это будет фантастически.

Ответы [ 2 ]

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

Поскольку вы уже знаете имя элемента на основе $lang, вы можете полностью исключить шаблон getvalueofnode.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" omit-xml-declaration="yes" encoding="utf-8" indent="yes" doctype-system="about:legacy-compat" />
  <xsl:variable name="configuration" select="document('settings.xml')/config/set[@id='local']" />
  <xsl:variable name="lang" select="response/responsedata/hit/language" />

  <xsl:template match="/">
    <html lang="{$lang}">
      <head lang="{$lang}"/>
      <body lang="{$lang}">
        <p>lang: <xsl:value-of select="$lang" /></p>
        <p>value: <xsl:value-of disable-output-escaping="yes" select="$configuration/header/*[name()=$lang]"/></p>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

Я также избавился от всех xsl:element и xsl:attribute. Обычно этого можно избежать путем непосредственного кодирования элементов и использования AVT (шаблоны значений атрибутов) для атрибутов.

Приведенная выше таблица стилей производит следующие выходные данные с использованием ваших входных XML-файлов (протестировано с Saxon 6.5.5 и Saxon-HE 9.3.0.5):

<!DOCTYPE html
  SYSTEM "about:legacy-compat">
<html lang="en">
   <head lang="en">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   </head>
   <body lang="en">
      <p>lang: en</p>
      <p>value: 

         <div id="header">
         <p>English code</p>
         </div>


      </p>
   </body>
</html>
0 голосов
/ 23 ноября 2011

Я не слишком уверен, правильно ли я понял вашу проблему, однако я все же попробую.

Когда вы пытаетесь получить значение с помощью шаблона getvalueofnode, вы указываете /header/en в качестве пути. Шаблон отрежет строку перед первой косой чертой и будет искать элемент с таким именем в вашей конфигурации. Случается, что отрубленное значение - это пустая строка, в результате которой ваш шаблон ищет элемент в конфигурации без имени (которого не существует).

Следовательно,

$content будет пустым фрагментом дерева результатов во втором вызове (первом рекурсивном вызове). Поскольку в этом шаблоне нет косой черты, выведите значение, которого там нет, и, следовательно, пустой фрагмент дерева результатов. Поскольку пустые фрагменты дерева при печати преобразуются в пустую строку, ваш вывод будет просто:

<p>value: </p>

Относительно решения: просто удалите косую черту при первом вызове шаблона. Это использовать:

<xsl:call-template name="getvalueofnode">
    <xsl:with-param name="path" select="concat('header/',$lang)" />
</xsl:call-template>

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

Кстати, ваш вызов getvalueofnode инкапсулирован в <p>, как и место, где он возвращает свое значение. Это приводит к вложенным тегам абзаца в окончательном выводе.

...