Использование тега ‹br /› в XML для XSLT

В настоящее время у меня возникают проблемы с преобразованием XML / XSLT в HTML, над которым я работаю. Короче говоря, я хочу использовать теги <br /> в теге XML, чтобы в файле HTML после преобразования отображался разрыв строки. После некоторых попыток я заставил это работать, но за счет некоторых других функций. А именно возможность выделять детали.

Сначала выгруженный XML-файл. Таким образом, существует несколько возможных тегов, каждый из которых содержит имя и фамилию. В этом случае я хочу, чтобы имя и фамилия анализировались в отдельной строке (отсюда и тег <br />). Кроме того, в некоторых случаях необходимо выделить имя или фамилию. В данном случае в строке 3 фамилия «Рука».

<swift_native>
<tag tag_code=":1:"><![CDATA[Jaco<br />Ronnie]]></tag>
<tag tag_code=":2:"><![CDATA[John<br />Doe]]></tag>
<tag tag_code=":2:"><![CDATA[Robbie<br />]]><highlight>The Hand</highlight></tag>
</swift_native>

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

outputНиже вы видите использованный XSLT-файл. Здесь вы можете видеть, что использование <xsl:apply-templates/> приведет к выделению, а <xsl:value-of select="." disable-output-escaping="yes"/> позволит мне правильно использовать <br />.

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- HTML Layout definition -->
<xsl:output method="html"/>
<xsl:template match="swift_native">

    <html>
        <head>
            <title>
                <xsl:apply-templates select="message_id"/>
            </title>
            <style type="text/css">
                #tbl1,#tbl2 {display:none;}
                #lnk1,#lnk2   {border:none;background:none;width:85px;}
                td {FONT-SIZE: 75%; MARGIN: 0px; COLOR: #000000;}
                td {FONT-FAMILY: verdana,helvetica,arial,sans-serif}
                a {TEXT-DECORATION: none;}
                table.subtable {border-collapse:collapse;}
                table.subtable td {border:1px solid black;}
            </style>
        </head>
        <body>
            <table cellpadding="3" width="100%" class="subtable">
                <tr bgcolor="#cccccc">
                    <td colspan="3">Block4</td>
                </tr>
                <xsl:apply-templates select="tag" />
            </table>
        </body>
    </html>
</xsl:template>

<!-- Variable definition -->

<xsl:template match="tag">
    <tr>
        <td>
            <b>
                <xsl:value-of select="@tag_code" />
            </b>
        </td>
        <td>
            <xsl:value-of select="." disable-output-escaping="yes"/>
        </td>
        <td>
            <xsl:apply-templates/>
        </td>
    </tr>
</xsl:template>

<xsl:template match="highlight">
    <span style="background-color:yellow;">
        <xsl:apply-templates/>
    </span>
</xsl:template>

</xsl:stylesheet>

Очевидно, возникает вопрос: знает ли кто-нибудь, как я могу использовать как тег <br />, так и выделение?


person Cobus    schedule 28.01.2013    source источник


Ответы (4)


CDATA говорит процессору интерпретировать содержимое как простой текст, а не как разметку. Вот почему disable-output-escaping необходимо, чтобы <br/> не отображался как &lt;br/&gt;.

Если вы хотите воспользоваться преимуществом disable-output-escaping, вам придется изменить способ выбора по содержимому тега.

Добавить шаблон

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

и измените строку value-of на

<xsl:apply-templates select="text()|*"/>
person harpo    schedule 28.01.2013
comment
Спасибо за быстрый ответ. Это несколько проясняет ситуацию. Одно небольшое замечание. тег <highlight> фактически находится за пределами CDATA. - person Cobus; 28.01.2013
comment
привет, когда тег ‹br/› появился в строке, затем disable-output-escaping = да, он не работает. - person Jatin Gadhiya; 06.08.2014

Одно из решений - использовать оба:

<xsl:template match="tag">
    <tr>
        <td>
            <b>
                <xsl:value-of select="@tag_code" />
            </b>
        </td>
        <td>
            <xsl:apply-templates/>
        </td>
    </tr>
</xsl:template>

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

<xsl:template match="highlight">
    <span style="background-color:yellow;">
        <xsl:apply-templates />
    </span>
</xsl:template>

Однако обратите внимание, что если вы это сделаете, вам необходимо убедиться, что любые текстовые значения в узлах <tag> правильно экранируются в CDATA и дважды экранируются за его пределами, то есть, а не

<tag tag_code=":2:"><![CDATA[Robbie & Bobbie <br />]]><highlight> &amp; The Hand</highlight></tag>

Вам потребуется:

<tag tag_code=":2:"><![CDATA[Robbie &amp; Bobbie<br />]]><highlight> &amp;amp; The Hand</highlight></tag>

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

Если вы можете гарантировать, что текст непосредственно под <tag> будет всегда в CDATA и что что-либо в нижних узлах (например, <highlight>s) не будет, тогда это будет немного проще. Вы можете заменить приведенный выше шаблон сопоставления текста следующим:

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

И тогда вам просто нужно убедиться, что содержимое CDATA правильно экранировано, и что все остальное является просто допустимым XML.

Наконец, если у вас есть некоторый контроль над исходными данными, вам следует подумать об отказе от CDATA и просто иметь <br /> прямо в <tag>:

<tag tag_code=":2:">Robbie<br /><highlight>The Hand</highlight></tag>

Затем вы можете использовать этот XSL, который намного надежнее, чем все, что использует disable-output-escaping:

<xsl:template match="tag">
    <tr>
        <td>
            <b>
                <xsl:value-of select="@tag_code" />
            </b>
        </td>
        <td>
            <xsl:apply-templates/>
        </td>
    </tr>
</xsl:template>

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

<xsl:template match="highlight">
    <span style="background-color:yellow;">
        <xsl:apply-templates />
    </span>
</xsl:template>
person JLRishe    schedule 28.01.2013

К счастью, есть и простое решение. Просто добавьте эту строку в свой xsl файл:

<xsl:template match="br"><br/></xsl:template>  

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

<tag tag_code=":1:">Jaco<br/>Ronnie</tag>

Аналогичным образом могут быть включены другие распространенные простые теги HTML. Вот пример ссылки на стили CSS жирным шрифтом, курсивом и т. Д., Но однострочный шрифт для каждого из них (как указано выше) тоже работает:

<xsl:template match="i|b|u|strong">
    <span>
        <xsl:attribute name="class">html_<xsl:value-of select="name(.)" /></xsl:attribute>
        <xsl:apply-templates />
    </span>
</xsl:template>

Если вы обнаружите, что делаете это часто, скопируйте их все в html.xsl и используйте xsl:include, чтобы использовать их при необходимости.

person user508402    schedule 04.01.2017
comment
Извините, это не сработает, поскольку <br /> на входе - это CDATA. Это то, о чем говорил @JLRishe в своем ответе. (Параграф, начинающийся с «Наконец», где обсуждается отказ от CDATA.) - person Daniel Haley; 05.01.2017
comment
Ага. CDATA больше не нужен, это правда. Используйте гораздо более интуитивно понятный <tag tag_code=":1:">Jaco<br />Ronnie</tag> - person user508402; 05.01.2017
comment
Имейте в виду, что большинство процессоров XSL преобразуют <br /> в <br></br>, что аналогично терминам XML, но не HTML. HTML будет читать <br></br> как два <br>-тега, потому что <br>-тег является недействительным тегом в HTML и не должен иметь закрывающего тега. В этом случае вы должны использовать что-то вроде этого: <xsl:value-of disable-output-escaping="yes">&lt;br /&gt;</xsl:value-of> - person Robert S.; 02.02.2017

если вы хотите сделать в HTML это

все, что вам нужно, это сделать в XLS:

<br></br>
person Amirouche Zeggagh    schedule 12.07.2019
comment
В XHTML рекомендуется использовать минимальный самозакрывающийся синтаксис для пустых элементов, например <br />, поскольку альтернативный синтаксис <br></br>, разрешенный XML, может давать неопределенные результаты в пользовательских агентах (w3.org / TR / xhtml1 / # C_2). Фактически, текущая версия HTML (v5) утверждает, что можно использовать только <br> (с опущенным конечным тегом - html.spec.whatwg.org/#the-br-element) и самозакрывание не требуется, но очевидно, что XML не будет рассматривать это использование как правильно сформированное. - person w5m; 01.04.2020