Изменение порядка нескольких братьев и сестер на основе свойства - PullRequest
1 голос
/ 22 декабря 2010

Я хочу создать HTML-файл, подобный этому примеру:

Английский

Alt

En Lorem ipsum dolor sit amet, consitteur adipiscing elit.

Nunc Rutrum, Eros Sit Amet Ornare Faucibus.

Français

Fr Lorem Ipsum Dolor Sit Amet, Concetetur Adipiscing Elit.

Nunc Rutrum, Eros Sitamet ornare faucibus.

Из следующего примера источника XML, над которым у меня нет контроля:

<?xml version="1.0" encoding="ISO-8859-1"?>
<content id="">
    <header language="en">
        <enabled>true</enabled>
        <img src="http://i.stack.imgur.com/xGCNw.gif" />
        <!-- more header-related elements -->
    </header>
    <header language="fr">
        <enabled>false</enabled>
        <img src="" />
        <!-- more header-related elements -->
    </header>
    <html language="en" type="source">
    <![CDATA[
        <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
        <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
        ]]>
    </html>
    <html language="fr" type="source">
    <![CDATA[
        <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
        <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
        ]]>
    </html>
</content>

Итак, я написал этот XSLT для этого:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <h1>English</h1>
        <hr/>
        <xsl:for-each select="content/header">
            <xsl:call-template name="header">
                <xsl:with-param name="lang">en</xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>
        <xsl:for-each select="content/html">
            <xsl:call-template name="html">
                <xsl:with-param name="lang">en</xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>
        <hr/>
        <h1>Français</h1>
        <hr/>
        <xsl:for-each select="content/header">
            <xsl:call-template name="header">
                <xsl:with-param name="lang">fr</xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>
        <xsl:for-each select="content/html">
            <xsl:call-template name="html">
                <xsl:with-param name="lang">fr</xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="header" match="*">
        <xsl:param name='lang'/>
        <xsl:if test="current()[@language=$lang]">
            <xsl:if test="enabled[normalize-space(text())='true']">
                <xsl:call-template name="image"/>
                <!-- more header-related elements -->
            </xsl:if>
        </xsl:if>
    </xsl:template>

    <xsl:template name="image" match="*">
        <xsl:if test="img[not(normalize-space(@src)='')]">
            <xsl:copy-of select="img"/>
        </xsl:if>
    </xsl:template>

    <xsl:template name="html" match="*">
        <xsl:param name='lang'/>
        <xsl:if test="current()[@language=$lang]">
            <xsl:value-of select="node()" disable-output-escaping="yes" />
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

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

Несколько примечаний, представляющих интерес:

  • Преобразование скорость не имеет значения, хотя было бы интересно узнать больше об этом аспекте.
  • Преобразования никогда не потребуются для обработки XML-документов, которые кодируют более двух примеров языков (ru и fr ).

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

Ответы [ 2 ]

1 голос
/ 22 декабря 2010

Это преобразование не содержит никаких условных инструкций XSLT или любых именованных шаблонов :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <my:langs>
  <lang short="en">English</lang>
  <lang short="fr">Français</lang>
 </my:langs>

 <xsl:variable name="vLangs" select="document('')/*/my:langs/*"/>

 <xsl:template match="header">
  <xsl:apply-templates select="node()|@*"/>
  <hr/>
  <xsl:apply-templates select=
        "../html[@language=current()/@language]/text()"/>
 </xsl:template>

 <xsl:template match="header/@language">
  <h1><xsl:value-of select="$vLangs[@short=current()]"/></h1>
 </xsl:template>

 <xsl:template match="header[enabled='true']/img[@src and not(@src='')]">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="html/text()">
  <xsl:value-of select="." disable-output-escaping="yes"/>
 </xsl:template>

 <xsl:template match="html|text()"/>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<content id="">
    <header language="en">
        <enabled>true</enabled>
        <img src="http://i.stack.imgur.com/xGCNw.gif" />
        <!-- more header-related elements -->
    </header>
    <header language="fr">
        <enabled>false</enabled>
        <img src="" />
        <!-- more header-related elements -->
    </header>
    <html language="en" type="source">
    <![CDATA[
             <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
             <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
             ]]>
   </html>
    <html language="fr" type="source">
    <![CDATA[
            <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
            <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
            ]]>
 </html>
</content>

желаемый, правильный результат получается :

<h1>English</h1>
<img src="http://i.stack.imgur.com/xGCNw.gif" />
<hr />

             <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
             <p>Nunc rutrum, eros sit amet ornare faucibus.</p>

   <h1>Français</h1>
<hr />

            <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
            <p>Nunc rutrum, eros sit amet ornare faucibus.</p>

Примечание :

  1. Использование шаблонов и сопоставление с образцом .

  2. Использование <xsl:apply-templates>

  3. Использование предикатов как в шаблоне совпадения шаблонов, так и для выбора необходимого списка узлов в <xsl:apply-templates>

1 голос
/ 22 декабря 2010

Вот как бы я написал это:

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

<my:language-labels>
    <lang code="en" label="English"/>
    <lang code="fr" label="Francais"/>
</my:language-labels>

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

<xsl:template match="header">
    <xsl:variable name="curLang" select="@language"/>
    <h1>
        <xsl:value-of select="document('')/*/my:language-labels/lang[@code = $curLang]/@label"/>
    </h1>
    <hr/>
    <xsl:copy-of select="img[not(normalize-space(@src) = '')][../enabled[normalize-space() = 'true']]"/>
    <xsl:value-of select="../html[@language = $curLang]" disable-output-escaping="yes"/>
 </xsl:template>

 </xsl:stylesheet>

Ваш пример HTML выглядит испорченным, поэтому я могу ошибаться. Мой результат:

<h1>English</h1>
<hr>
<img src="http://i.stack.imgur.com/xGCNw.gif"> 
<p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Nunc rutrum, eros sit amet ornare faucibus.</p>
<h1>Francais</h1> 
<hr>
<p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Nunc rutrum, eros sit amet ornare faucibus.</p>

Примечания:

  1. Использовать предикаты. Это очень мощный инструмент.
  2. Храните закодированные данные в одном месте, если это возможно.
  3. apply-templates это не таинственный инструмент, а очень важный механизм XSLT.
  4. Вы можете вызывать normalize-space и другие функции без фактической передачи аргумента, если нужный аргумент является элементом context.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...