Изменение xml на xhtml через xslt

#xml #parsing #xslt #xhtml

#xml #синтаксический анализ #xslt #xhtml

Вопрос:

я пытаюсь преобразовать XML-файл из ECB в xhtml через xslt, но у меня где-то ошибка.

Это XML-файл

 <?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="output.xsl"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" 
    xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time='2011-10-18'>
            <Cube currency='USD' rate='1.3676'/>
            <Cube currency='JPY' rate='104.97'/>
            <Cube currency='BGN' rate='1.9558'/>
            <Cube currency='CZK' rate='24.925'/>
            <Cube currency='DKK' rate='7.4456'/>
            <Cube currency='GBP' rate='0.87020'/>
            <Cube currency='HUF' rate='298.40'/>
            <Cube currency='LTL' rate='3.4528'/>
            <Cube currency='LVL' rate='0.7057'/>
            <Cube currency='PLN' rate='4.3684'/>
            <Cube currency='RON' rate='4.3525'/>
            <Cube currency='SEK' rate='9.1589'/>
            <Cube currency='CHF' rate='1.2348'/>
            <Cube currency='NOK' rate='7.7605'/>
            <Cube currency='HRK' rate='7.4715'/>
            <Cube currency='RUB' rate='42.8780'/>
            <Cube currency='TRY' rate='2.5568'/>
            <Cube currency='AUD' rate='1.3489'/>
            <Cube currency='BRL' rate='2.4332'/>
            <Cube currency='CAD' rate='1.4018'/>
            <Cube currency='CNY' rate='8.7262'/>
            <Cube currency='HKD' rate='10.6373'/>
            <Cube currency='IDR' rate='12061.31'/>
            <Cube currency='ILS' rate='4.9936'/>
            <Cube currency='INR' rate='67.5500'/>
            <Cube currency='KRW' rate='1567.60'/>
            <Cube currency='MXN' rate='18.5187'/>
            <Cube currency='MYR' rate='4.2854'/>
            <Cube currency='NZD' rate='1.7360'/>
            <Cube currency='PHP' rate='59.256'/>
            <Cube currency='SGD' rate='1.7423'/>
            <Cube currency='THB' rate='42.095'/>
            <Cube currency='ZAR' rate='11.0432'/>
        </Cube>
    </Cube>
</gesmes:Envelope>
 

и вот мой файл XSLT

 <?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" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
 
    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
            <title>Exchange rates</title>

     </head>

        <body>
            <table>
                <tr>
                    <th>Rate</th>
                </tr>
            <xsl:for-each select="/gesmes:Envelope/Cube/Cube/Cube">
             <tr>
                    <td><xsl:value-of select="Cube/[@currency='USD']"/></td>

                </tr>
                </xsl:for-each>

            </table>
        </body>
        </html>
    </xsl:template>
</xsl:stylesheet>
 

И результат выглядит так:

 USD 1.3676
JPY 104.97
BGN 1.9558
 

и так далее

Мне нужно решение, а не способ получить правильный исходный код.

Ответ №1:

ХОРОШО! Я не видел.

Ваша основная проблема связана с пространством имен: движок XSLT не знает, что такое gesmes, поэтому вам нужно сообщить об этом. Поэтому вам нужно добавить его в свой тег xsl: stylesheet.

  • xmlns:gesmes=»http://www.gesmes.org/xml/2002-08-01 «

Вам нужно добавить и назвать пространство имен для пространства имен по умолчанию вашего xml :

  • xmlns: xx=»http://www.ecb.int/vocabulary/2002-08-01/eurofxref » итак, ваша таблица стилей будет начинаться с :

    <xsl:версия таблицы стилей=»1.0″ xmlns:xsl=»http://www.w3.org/1999/XSL/Transform » xmlns:gesmes=»http://www.gesmes.org/xml/2002-08-01 » xmlns:xx=»http://www.ecb.int/vocabulary/2002-08-01/eurofxref «>

для каждого из них будет: <xsl:для каждого select=»/gesmes:Envelope/xx:Cube/xx:Cube/xx:Cube»>

И это должно сработать … но я предлагаю вам использовать шаблон вместо xsl: для каждого

Вот решение, которое я предлагаю: ХОРОШО! Я не видел.

Ваша основная проблема связана с пространством имен: движок XSLT не знает, что такое gesmes, поэтому вам нужно сообщить об этом. Поэтому вам нужно добавить его в свой тег xsl: stylesheet.

  • xmlns:gesmes=»http://www.gesmes.org/xml/2002-08-01 «

Вам нужно добавить и назвать пространство имен для пространства имен по умолчанию вашего xml :

  • xmlns: xx=»http://www.ecb.int/vocabulary/2002-08-01/eurofxref » итак, ваша таблица стилей будет начинаться с :

    <xsl:версия таблицы стилей=»1.0″ xmlns:xsl=»http://www.w3.org/1999/XSL/Transform » xmlns:gesmes=»http://www.gesmes.org/xml/2002-08-01 » xmlns:xx=»http://www.ecb.int/vocabulary/2002-08-01/eurofxref «>

для каждого из них будет: <xsl:для каждого select=»/gesmes:Envelope/xx:Cube/xx:Cube/xx:Cube»>

И это должно сработать … но я предлагаю вам использовать шаблон вместо xsl: для каждого

Вот решение, которое я предлагаю :

 <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
                xmlns:xx="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<xsl:output method="html" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
<xsl:template match="/">
  <html xmlns="http://www.w3.org/1999/xhtml">
    <body>
      <table>
        <tr><th>Rate</th></tr>
        <xsl:apply-templates select="gesmes:Envelope/xx:Cube/xx:Cube/xx:Cube" />
      </table>
    </body>
  </html>
</xsl:template>

<xsl:template match="xx:Cube">
  <tr>
    <td><xsl:value-of select="@currency"/></td>
    <td><xsl:value-of select="@rate"/></td>
  </tr>
</xsl:template>
</xsl:stylesheet>
 

Ответ №2:

Кажется, вы хотите что-то вроде этого (я только что отредактировал ваш код — мое собственное решение было бы другим):

 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
 xmlns:ecb="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"
 >
    <xsl:output method="xml" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                <title>Exchange rates</title>
            </head>
            <body>
                <table>
                    <tr>
                        <th>Currency</th>
                        <th>Rate</th>
                    </tr>
                    <xsl:for-each select="/gesmes:Envelope/ecb:Cube/ecb:Cube/ecb:Cube">
                        <tr>
                            <td>
                                <b><xsl:value-of select="@currency"/></b>
                            </td>
                            <td>
                                <xsl:value-of select="@rate"/>
                            </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>
 

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

 <gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
 xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time='2011-10-18'>
            <Cube currency='USD' rate='1.3676'/>
            <Cube currency='JPY' rate='104.97'/>
            <Cube currency='BGN' rate='1.9558'/>
            <Cube currency='CZK' rate='24.925'/>
            <Cube currency='DKK' rate='7.4456'/>
            <Cube currency='GBP' rate='0.87020'/>
            <Cube currency='HUF' rate='298.40'/>
            <Cube currency='LTL' rate='3.4528'/>
            <Cube currency='LVL' rate='0.7057'/>
            <Cube currency='PLN' rate='4.3684'/>
            <Cube currency='RON' rate='4.3525'/>
            <Cube currency='SEK' rate='9.1589'/>
            <Cube currency='CHF' rate='1.2348'/>
            <Cube currency='NOK' rate='7.7605'/>
            <Cube currency='HRK' rate='7.4715'/>
            <Cube currency='RUB' rate='42.8780'/>
            <Cube currency='TRY' rate='2.5568'/>
            <Cube currency='AUD' rate='1.3489'/>
            <Cube currency='BRL' rate='2.4332'/>
            <Cube currency='CAD' rate='1.4018'/>
            <Cube currency='CNY' rate='8.7262'/>
            <Cube currency='HKD' rate='10.6373'/>
            <Cube currency='IDR' rate='12061.31'/>
            <Cube currency='ILS' rate='4.9936'/>
            <Cube currency='INR' rate='67.5500'/>
            <Cube currency='KRW' rate='1567.60'/>
            <Cube currency='MXN' rate='18.5187'/>
            <Cube currency='MYR' rate='4.2854'/>
            <Cube currency='NZD' rate='1.7360'/>
            <Cube currency='PHP' rate='59.256'/>
            <Cube currency='SGD' rate='1.7423'/>
            <Cube currency='THB' rate='42.095'/>
            <Cube currency='ZAR' rate='11.0432'/></Cube></Cube>
</gesmes:Envelope>
 

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

 <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>Exchange rates</title>
    </head>
    <body>
        <table>
            <tr>
                <th>Currency</th>
                <th>Rate</th>
            </tr>
            <tr>
                <td>
                    <b>USD</b>
                </td>
                <td>1.3676</td>
            </tr>
            <tr>
                <td>
                    <b>JPY</b>
                </td>
                <td>104.97</td>
            </tr>
            <tr>
                <td>
                    <b>BGN</b>
                </td>
                <td>1.9558</td>
            </tr>
            <tr>
                <td>
                    <b>CZK</b>
                </td>
                <td>24.925</td>
            </tr>
            <tr>
                <td>
                    <b>DKK</b>
                </td>
                <td>7.4456</td>
            </tr>
            <tr>
                <td>
                    <b>GBP</b>
                </td>
                <td>0.87020</td>
            </tr>
            <tr>
                <td>
                    <b>HUF</b>
                </td>
                <td>298.40</td>
            </tr>
            <tr>
                <td>
                    <b>LTL</b>
                </td>
                <td>3.4528</td>
            </tr>
            <tr>
                <td>
                    <b>LVL</b>
                </td>
                <td>0.7057</td>
            </tr>
            <tr>
                <td>
                    <b>PLN</b>
                </td>
                <td>4.3684</td>
            </tr>
            <tr>
                <td>
                    <b>RON</b>
                </td>
                <td>4.3525</td>
            </tr>
            <tr>
                <td>
                    <b>SEK</b>
                </td>
                <td>9.1589</td>
            </tr>
            <tr>
                <td>
                    <b>CHF</b>
                </td>
                <td>1.2348</td>
            </tr>
            <tr>
                <td>
                    <b>NOK</b>
                </td>
                <td>7.7605</td>
            </tr>
            <tr>
                <td>
                    <b>HRK</b>
                </td>
                <td>7.4715</td>
            </tr>
            <tr>
                <td>
                    <b>RUB</b>
                </td>
                <td>42.8780</td>
            </tr>
            <tr>
                <td>
                    <b>TRY</b>
                </td>
                <td>2.5568</td>
            </tr>
            <tr>
                <td>
                    <b>AUD</b>
                </td>
                <td>1.3489</td>
            </tr>
            <tr>
                <td>
                    <b>BRL</b>
                </td>
                <td>2.4332</td>
            </tr>
            <tr>
                <td>
                    <b>CAD</b>
                </td>
                <td>1.4018</td>
            </tr>
            <tr>
                <td>
                    <b>CNY</b>
                </td>
                <td>8.7262</td>
            </tr>
            <tr>
                <td>
                    <b>HKD</b>
                </td>
                <td>10.6373</td>
            </tr>
            <tr>
                <td>
                    <b>IDR</b>
                </td>
                <td>12061.31</td>
            </tr>
            <tr>
                <td>
                    <b>ILS</b>
                </td>
                <td>4.9936</td>
            </tr>
            <tr>
                <td>
                    <b>INR</b>
                </td>
                <td>67.5500</td>
            </tr>
            <tr>
                <td>
                    <b>KRW</b>
                </td>
                <td>1567.60</td>
            </tr>
            <tr>
                <td>
                    <b>MXN</b>
                </td>
                <td>18.5187</td>
            </tr>
            <tr>
                <td>
                    <b>MYR</b>
                </td>
                <td>4.2854</td>
            </tr>
            <tr>
                <td>
                    <b>NZD</b>
                </td>
                <td>1.7360</td>
            </tr>
            <tr>
                <td>
                    <b>PHP</b>
                </td>
                <td>59.256</td>
            </tr>
            <tr>
                <td>
                    <b>SGD</b>
                </td>
                <td>1.7423</td>
            </tr>
            <tr>
                <td>
                    <b>THB</b>
                </td>
                <td>42.095</td>
            </tr>
            <tr>
                <td>
                    <b>ZAR</b>
                </td>
                <td>11.0432</td>
            </tr>
        </table>
    </body>
</html>
 

Мои собственные решения были бы больше похожи на это:

 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
 xmlns:ecb="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"
 exclude-result-prefixes="ecb gesmes">
    <xsl:output method="xml" encoding="utf-8"
     doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
     doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

    <xsl:strip-space elements="*"/>

    <xsl:template match="ecb:Cube/ecb:Cube">
        <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                <title>Exchange rates</title>
            </head>
            <body>
                <table>
                    <tr>
                        <th>Currency</th>
                        <th>Rate</th>
                    </tr>
                 <xsl:apply-templates/>
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="ecb:Cube/ecb:Cube/ecb:Cube" priority="5">
            <tr>
                <td>
                    <b><xsl:value-of select="@currency"/></b>
                </td>
                <td>
                    <xsl:value-of select="@rate"/>
                </td>
            </tr>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>
 

Комментарии:

1. И затем я просто запускаю файл .xsl? Поскольку это показывает мне неправильно, я вижу исходный код, и это неправильно.

2. @user1006959: Вам нужно скопировать код, вставить его в текстовый редактор и сохранить в файле. Затем примените преобразование в этом файле к файлу, содержащему исходный XML (используя любой метод, который вы предпочитаете, например, из командной строки). Я никогда не публикую непроверенные решения. Как и в этом случае, я всегда запускаю решение и проверяю, дает ли оно ожидаемый результат. Затем я просто копирую код и вставляю его в свой ответ SO. Если у вас возникли проблемы с запуском преобразования, пожалуйста, просто задайте другой вопрос.

3. Хорошо, я создал два новых файла. Я скопировал исходный код в эти файлы. Но когда я запускаю его в Opera, Chrome или Safari, он показывает мне только этот «Курс валюты». У вас есть какие-либо идеи?

4. @user1006959: это худший метод выполнения преобразования, о котором я знаю. В любом случае, убедитесь, что имя файла в таблице стилей xml PI совпадает с именем файла, в котором вы сохранили решение. Кроме того, попробуйте изменить метод вывода на «html», то есть: <xsl:output method="html: .../>

5. Спасибо, но мне это не помогает.

Ответ №3:

XSLT:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"
                xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01">
    <xsl:output method="html" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
                doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>


    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                <title>Exchange rates</title>
            </head>

            <body>
                <table>
                    <tr>
                        <th>Rate</th>
                        <th>Value</th>
                    </tr>
                    <xsl:apply-templates select="//ns:Cube/ns:Cube"/>


                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="ns:Cube">
        <tr xmlns="http://www.w3.org/1999/xhtml">
            <td>
                <xsl:value-of select="@currency"/>
            </td>
            <td>
                <xsl:value-of select="@rate"/>
            </td>
        </tr>
    </xsl:template>

</xsl:stylesheet>
 

Вывод:

 Rate Value 
USD 1.3676 
JPY 104.97 
BGN 1.9558 
CZK 24.925 
DKK 7.4456 
GBP 0.8702 
HUF 298.4 
LTL 3.4528 
LVL 0.7057 
PLN 4.3684 
RON 4.3525 
SEK 9.1589 
CHF 1.2348 
NOK 7.7605 
HRK 7.4715 
RUB 42.878 
TRY 2.5568 
AUD 1.3489 
BRL 2.4332 
CAD 1.4018 
CNY 8.7262 
HKD 10.6373 
IDR 12061.31 
ILS 4.9936 
INR 67.55 
KRW 1567.6 
MXN 18.5187 
MYR 4.2854 
NZD 1.736 
PHP 59.256 
SGD 1.7423 
THB 42.095 
ZAR 11.0432