Вызов одного и того же шаблона xsl: для разных имен узлов одного и того же сложного типа - PullRequest
3 голосов
/ 24 марта 2010

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

<?xml version="1.0" encoding="UTF-8"?>
<RootNode>
    <Name>Bob</Name>
    <ContactDetails>
        <Address>
            <Line1>1 High Street</Line1>
            <Town>TownName</Town>
            <Postcode>AB1 1CD</Postcode>
        </Address>
        <Email>test@test.com</Email>
    </ContactDetails>
    <AltContactDetails>
        <Address>
            <Line1>3 Market Square</Line1>
            <Town>TownName</Town>
            <Postcode>EF2 2GH</Postcode>
        </Address>
        <Email>bob@bob.com</Email>
    </AltContactDetails>
</RootNode>

Я написал таблицу стилей XSL следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <PersonsName>
            <xsl:value-of select="RootNode/Name"/>
        </PersonsName>
        <xsl:call-template name="ContactDetails">
            <xsl:with-param name="data"><xsl:value-of select="RootNode/ContactDetails"/></xsl:with-param>
            <xsl:with-param name="elementName"><xsl:value-of select="'FirstAddress'"/></xsl:with-param>
        </xsl:call-template>
        <xsl:call-template name="ContactDetails">
            <xsl:with-param name="data"><xsl:value-of select="RootNode/AltContactDetails"/></xsl:with-param>
            <xsl:with-param name="elementName"><xsl:value-of select="'SecondAddress'"/></xsl:with-param>
        </xsl:call-template>
    </xsl:template>
    <xsl:template name="ContactDetails">
        <xsl:param name="data"></xsl:param>
        <xsl:param name="elementName"></xsl:param>
        <xsl:element name="{$elementName}">
            <FirstLine>
                <xsl:value-of select="$data/Address/Line1"/>
            </FirstLine>

            <Town>
                <xsl:value-of select="$data/Address/Town"/>
            </Town>
            <PostalCode>
                <xsl:value-of select="$data/Address/Postcode"/>
            </PostalCode>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Когда я пытаюсь запустить таблицу стилей, мне жалуются, что мне нужно:

Чтобы использовать фрагмент дерева результатов в выражении пути, используйте exsl: node-set () или укажите версию 1.1

Я не хочу переходить на версию 1.1 .. Так кто-нибудь знает, как заставить exsl: node-set () работать в приведенном выше примере?

Или если кто-то знает, как лучше применить один и тот же шаблон к двум разным разделам, то это тоже очень поможет?

Спасибо

Dave

Ответы [ 2 ]

9 голосов
/ 24 марта 2010

Вы скручиваете это от неправильного конца (неправильный конец почти всегда: пытаетесь применить парадигму императивного программирования к XSLT).

Это действительно легко сделать с помощью сопоставления с шаблоном.

<xsl:template match="RootNode">
  <PersonsName>
    <xsl:value-of select="Name"/>
  </PersonsName>
  <xsl:apply-templates select="ContactDetails|AltContactDetails" />
</xsl:template>

<xsl:template match="ContactDetails|AltContactDetails">
  <xsl:copy>
    <FirstLine>
      <xsl:value-of select="Address/Line1"/>
    </FirstLine>
    <Town>
      <xsl:value-of select="Address/Town"/>
    </Town>
    <PostalCode>
      <xsl:value-of select="Address/Postcode"/>
    </PostalCode>
  </xsl:copy>
</xsl:template>

Откажитесь от идеи, что вы должны указывать процессору XSLT, что делать (через создание именованных шаблонов и называть их «императивным стилем»).

Процессор XSLT выбирает, какие шаблоны вызывать. Начиная с корня (/), он рекурсивно проверяет соответствие шаблонов для каждого посещаемого узла. Он самостоятельно просматривает ваш входной XML - ваша единственная задача - предоставить ему соответствующие шаблоны для тех узлов, которые вы хотите обработать особым образом.

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

2 голосов
/ 24 марта 2010

Почему бы не сделать шаблон

<xsl:template match="ContactDetails|AltContactDetails">

и выполнить тест для определения имени выходного элемента внутри шаблона?

...