Русский XML FAQ

Введение

Java

XSLT

Есть большой и полезный англоязычный XSLT FAQ и онлайн-версия книги «Технология XSLT» с готовыми решениями (например, группировка, рекурсия, циклы, операции над множествами).

Прочее

О русском XML FAQ

Когда-то было так:

Русский XML FAQ создаётся силами добровольцев. Каждый может добавить пару вопрос-ответ в faq или дополнить существующий ответ. FAQ постоянно пополняется и изменяется, самая последняя версия доступна по адресу <http://wiki.xmlhack.ru/Faq.html>.

Но потом wiki-раздел на xmlhack.ru был закрыт, а вопросы и ответы собраны в один файл и выложены по адресу <http://xmlhack.ru/faq.html>. Последнее обновление было сделано в конце 2006-го года, дополнений и улучшений не ожидается. Если есть вопросы, задавайте их в xml-форумах на xmlhack.ru.

Что такое XML?

XML — это способ записи данных с помощью тегов, атрибутов и других простых конструкций. А в обобщённом смысле — это семейство технологий для обработки структурированных данных.

Смотрите также http://xmlhack.ru/forum/xml/topic538.html

Простой пример XML:

<article id="hw">
 <title>Привет</title>
 <para>Привет, <object>мир</object>!</para>
</article>

Основные сайты и книги

Англоязычные ресурсы.

Русскоязычные ресурсы:

xmlhack.ru: Новости XML, статьи, советы, переводы, ссылки, XML FAQ, форумы.
raleigh.ru: Учебники по XSLT, XPath, статьи, шлюз в fido7.ru.xml
XML-форумы: Обсуждение вопросов, связанных с XML
fido7.ru.xml: Конференция fido.
Школы Консорциума W3C: Введение в основные XML-технологии.
IBM developerWorks, XML: Русская версия
Книги: Книги по XML на books.ru

В бумажном виде рекомендуем книгу Алексея Валикова «Технология XSLT». Она частично опубликована на сервере xmlhack.ru.

Прочее:

ru_xml: ЖЖ-сообщество, посвящённое XML
xhtml.ru: Сайт, посвящённый XHTML
ru_xhtml: ЖЖ-сообщество, посвящённое XHTML
Библиотека онтологий: Web-онтологии. Практика применения
Технологии web-сервисов: Новости, статьи, форумы

Элементы или атрибуты?

Выбор между элементом или атрибутом.

<note date="xxx"> ... </note>

или

<note> <date>xxx</date> ... </note>

?

Некоторые идеи можно найти по адресу http://www.oasis-open.org/cover/elementsAndAttrs.html

Перевод «содержательной части» и дополнительные мысли есть в форумах xmlhack.ru:

Этот вопрос также обсуждался в fido7.ru.xml: http://tinyurl.com/ceek4

Русские буквы, FOP

Настройка FOP на русский язык описана на сайте Russian FOP: <http://www.openmechanics.org/rusfop/> (автор — Алексей (aka Achtung) V. Алишевских).


От:     Alex Tyurin <alext plastic yi org>
Тема:   Re: 2 Sergey Astakhov (про руские буковки)
Группа: fido7.ru.java

> >   А может стоит добавить в трактат про русские буквы раздел об XML? В
> > частности про борьбу с Xerces, Xalan, FOP. Вопросы про них здесь в
> > последнее время весьма часто появляются.
> >
> >   Может кто-то из тех, кто уже сталкивался с этой проблемой напишет
> > кусочек про ЭТО для экономии времени... :)
Предлагаю описание решения проблемы русификации FOP:

1. Пропатчить Xerces:
 -   Выкачать исходники Xerces
 -   В файл Encodings.java добавить строчки:
      new EncodingInfo( "Cp1251", "Cp1251", 0xFF ),
      new EncodingInfo( "Windows-1251", "Cp1251", 0xFF ),.
- Откомпилировать Хerces (набрать команду build.bat или build.sh - в
зависимости от операционной системы)
- Получившийся в результате компилляции файл xerces.jar (в каталоге build)
скопировать в каталог lib у FOP
-  FOP (0.20.1).

2. В файле FO (или XML и XSL) написать в заголовке:
    <?xml version="1.0" encoding="WINDOWS-1251"?>
     Теперь можно писать в этом файле по русски в кодировке Cp1251 или
UNICODE

3. В соответствующий каталог (в данном случае c:\fop-0.20.1\conf\fonts\)
скопировать файлы ttf из системного каталога Windows. Для Arial
normal/normal, normal/bold, italic/normal и italic/bold нужны файлы
arial.ttf, arialbd.ttf, ariali.ttf и arialbi.ttf.

4. Сгенерировать файлы описаний шрифтов (типа arial.xml).
Для этого для каждого шрифта нужно выполнить команду:
java -cp
.;c:\fop-0.20.1\build\fop.jar;c:\fop-0.20.1\lib\batik.jar;c:\fop-0.20.1\lib\
xalan-2.0.0.jar;c:\fop-0.20.1\lib\xerces.jar;c:\fop-0.20.1\lib\jimi-1.0.jar
org.apache.fop.fonts.apps.TTFReader fonts\arial.ttf fonts\arial.xml  (это
для Arial normal/normal)

5. В FOP  добавить в conf/userconfig.xml описание шрифта с русскими буквами,
типа:
<font metrics-file="c:\fop-0.20.1\conf\fonts\arial.xml" kerning="yes"
embed-file="c:\fop-0.20.1\conf\fonts\arial.ttf">
    <font-triplet name="Arial" style="normal" weight="normal"/>
    <font-triplet name="ArialMT" style="normal" weight="normal"/>
 </font> .
Аналогично добавляются Arial normal/bold, italic/normal и italic/bold.

6. При вызове FOP из командной строки после org.apache.fop.apps.Fop
писать  -c c:\fop-0.20.1\conf\userconfig.xml
Если нужно использовать FOP из сервлета, то нужно в сервлете после строчки
Driver driver = new Driver();
добавить строчки:
           String userConfig = "fonts/userconfig.xml"; //Каталог fonts
(c:\weblogic\fonts) был создан исключительно для удобства.
            File userConfigFile = new File(userConfig);
            Options options = new Options(userConfigFile);
Тогда расположение файлов ttf в файле userconfig.xml можно указать
относительно корня сервера приложения, без указания абсолютного пути:
<font metrics-file="fonts/arial.xml" kerning="yes"
embed-file="fonts/arial.ttf">
    <font-triplet name="Arial" style="normal" weight="normal"/>
    <font-triplet name="ArialMT" style="normal" weight="normal"/>
 </font>

7. В файле FO (или XML и XSL) перед использованием шрифта писать:
      font-family="Arial"
      font-weight="bold" (Если используется Arial bold)
      font-style="italic" (Если используется Arial italic)

8. Скомпиллированный файл xerces.jar указать в путях сервера приложений
(если нужно использовать FOP из сервлета).

PS. Таким способом мною были добавлены шрифты Arial и Times. Этого вполне
хватает для генерации отчетов.

Русские буквы, Xerces, Xalan

Важный документ, помогающий справиться со многими проблемами: «Java: русские буквы и не только...»


Сохраняем XML в Xalan или Xerces. Результат есть, но в виде:

&#1053;&#1072;&#1079;&#1074;&#1072;

Где грабли?

Ответ 1

Если в Encodings.java последний параметр конструктора сделать не 0xFF, а 0xFFFF,

new EncodingInfo("Cp1251", "Cp1251", 0xFFFF)

то xerces будет выводить XML-документы в данной кодировке без преобразования русских букв в последовательности вида &#xxxx; Этот совет касается по крайней мере некоторых старых версий xerces, 1.2.x, на более новых не проверялся, хотя структура Encodings.java не изменилась, т.е. все должно работать по-старому.

<shikov rinet ru>

Ответ 2

Суть проблемы: даже после ковыряния в исходниках xerces'а xalan ругался на кодировку. Всё пофиксилось после прочтения соответствующей приписки.

Лежит эта приписка в исходниках xalan: <xalan-j\src\org\apache\xalan\xpath\dtm\package.html>

Вкратце, мысль следующая: чтобы xalan использовал пропатченный xerces, нужно при создании XSLTProcessor'а использовать синтаксис:

org.apache.xalan.xslt.XSLTProcessor xsltProc =
org.apache.xalan.xslt.XSLTProcessorFactory.getProcessor(
         new org.apache.xalan.xpath.xdom.XercesLiaison());

вместо дефолтного .getProcessor() без параметров.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Другой вариант исправления был найден, когда я заставил ant'а собирать xalan-j:

в файле <org\apache\xalan\xpath\xml\FormatterToXML.java> после строки:

  s_revsize.put("KOI8-R",   new Character('\uFFFF'));

добавляются:

  s_revsize.put("CP1251",   new Character('\uFFFF'));
  s_revsize.put("CP866",    new Character('\uFFFF'));

После чего можно использовать .getProcessor() и не заморачиваться.

Sergey Kluchkowsky в fido7.ru.xml, Птн Окт 26 12:40:16 MSD 2001

Ответ 3

Объясняю по шагам последовательность для JDK 1.4.x:

  1. Создаёшь каталог %JAVA_HOME%\jre\lib\endorsed
  2. Копируешь туда http://people.comita.spb.ru/users/sergeya/java/XalanRusChars.jar
  3. Наслаждаешься результатом

Sergey Astakhov в fido7.ru.java, Thu, 11 Jul 2002 13:56:21 +0000 (UTC)

Комментарий 3а

Всё, что говорилось ранее, верно. Но можно ли как-нибудь обойтись без замены файлов вообще? У меня, например, нет доступа к папкам jvm, и я не могу заменить ни xalan.jar, ни rt.jar. Преобразовывать из utf-8 самому не трудно, но на это нужно время (не на написание кода - на выполнение). Кто-нибудь может посоветовать что-нибудь?

Можно url сайта, откуда можно скачать другой трансформер, но только не saxon, он конфликтует с Tomcat, а его параметры я также не могу изменять.

Комментарий 3б

Когда нет доступа к jvm, можно использовать опцию -Xbootclasspath примерно так:

java -Xbootclasspath/p:/home/iib/XalanRusChars.jar

Java: XML DOM Document -> XML String

Q: Имеется org.w3c.dom.Document, как получить строку, содержащую его XML представление?

A: Бывают сериализаторы, но можно и через JAXP:

/** Transformer factory. */
 protected static TransformerFactory transformerFactory;

 static {
  transformerFactory = TransformerFactory.newInstance();
 }

 /**
  * Serializes a source into a writer.
  * @param source to serialize.
  * @param writer writer to serialize into.
  * @throws TransformerException If an unrecoverable error occurs during the
  * course of the serialization.
  */
 public static void serialize(Source source, Writer writer)
  throws TransformerException
 {
  Transformer transformer = null;
  synchronized (transformerFactory)
 {
   transformer = transformerFactory.newTransformer();
  }
  transformer.transform(source, new StreamResult(writer));
 }

 /**
  * Serializes DOM node into a writer.
  * @param node DOM node to serialize.
  * @param writer writer to serialize into.
  * @throws TransformerException If an unrecoverable error occurs during the
  * course of the serialization.
  */
 public static void serialize(Node node, Writer writer)
  throws TransformerException
 {
  serialize(new DOMSource(node), writer);
 }

-- Aleksei Valikov в fido7.ru.java, Tue, 11 Feb 2003 14:16:55 +0000 (UTC)

Повторное использование тега при XSLT трансформации

>>Есть хмл
>>  <root>
>>    <client>Maxim</client>
>>  </root>
>> надо сделать из него Квитанцию и Уведомление.
>Я бы сделал так
>
><xsl:template match="root">
>    <xsl:for-each select="client">
>        <xsl:call-template name="kvit"/>
>        <xsl:call-template name="uved"/>
>    </xsl:for-each>
></xsl:template>
>
><xsl:template name="uved">
>    <xsl:text>Уведомление-</xsl:text><xsl:value-of select="."/>
></xsl:temlpate>
>
><xsl:template name="kvit">
>    <xsl:text>Квитанция-</xsl:text><xsl:value-of select="."/>
></xsl:temlpate>
>
>Обрати внимание, что есть <xsl:template match="..."> и 
><xsl:template name="...">

В этом случае лучше использовать режимы:

<xsl:template match="root">
     <xsl:apply-templates select="client" mode="kvit"/>
     <xsl:apply-templates select="client" mode="uved"/>
</xsl:template>

<xsl:template match="client" mode="uved">
    <xsl:text>Уведомление-</xsl:text><xsl:value-of select="."/>
</xsl:temlpate>

<xsl:template match="client" mode="kvit">
    <xsl:text>Квитанция-</xsl:text><xsl:value-of select="."/>
</xsl:temlpate>

Разница небольшая, но с режимами - стиль лучше.

-- Aleksei Valikov

Изменить значение переменной XSLT

Что-то как объявить переменную я понял, а как у нее значение изменить, чтобы не ругалось на повторное объявление?

Ответ 1

Никак. Это тебе не С, учись программировать без присваиваний.

Ответ 2

Переменные XSLT обсуждались в треде "Идеологический вопрос", ближе к концу: http://groups.google.com/groups?hl=ru&th=be43a163027897ff&seekm=998371731%40p69.f1609.n5020.z2.ftn#link1

Изменение переменной "на стеке"

Идея: использовать параметр вместо переменной.

<xsl:template name="t">
  <xsl:param name="a"></xsl:param>
  <xsl:value-of select="$a"/>
<xsl:if test="$a > 0"> <xsl:call-template name="t"><xsl:with-param name="a" select="$a - 1"/></xsl:call-template> </xsl:if> </xsl:template>

Использование:

<xsl:call-template name="t"><xsl:with-param name="a" select="'10'"/></xsl:call-template>

www.citforum.ru об XSLT

Q: Я прочитал статью на http://www.citforum.ru/internet/xml/part3.shtml и попробовал сделать так, как там написано. Почему у меня ничего не работает?

A: Потому что там описана настолько дремучая и устаревшая версия "якобы" XSLT, которая не соответствует никакому стандарту, и никем не поддерживается. Читайте нормальную документацию на w3c.org, ставьте MS XML не ниже 3.0 (с MSIE 6.0 уже стоит), и делайте как написано в Help от MS XML.

<shikov rinet ru>

URI пространства имён для XSLT

XLST-файл начинается с такого заголовка:

 <?xml version="1.0" encoding="кодировка">
 <xsl:stylesheet xmlns:xsl="URI" xsl:version="1.0">

URI должен быть таким:

 http://www.w3.org/1999/XSL/Transform

URI не должен быть таким:

 http://www.w3.org/TR/WD-xsl

<meta> с кодировкой в выводе XSLT

Как избавиться от <meta> с кодировкой в выводе (<xsl:output method="html" encoding="windows-1251"/> — всё прописано)?

ответ

xslt процессоры обязаны его генерировать в HTML режиме вывода и если есть элемент head — отсюда все твои варианты: либо выводить в режиме xml, либо без head, либо постпроцесс какой-нибудь. А чем она мешает-то?

-- Oleg Tkachenko в fido7.ru.java

комментарий

saxon умеет отключать мету:

The saxon:omit-meta-tag attribute

This attribute may be set on the xsl:output element when method="html". The normal action of the HTML output method, as specified in the XSLT standard, is to generate a <META> tag immediately after the <HEAD> tag, containing details of the media type and character encoding. Setting this attribute to "yes" causes this output to be suppressed. Typical usage is
<xsl:output method="html" saxon:omit-meta-tag="yes">

Форматирование текста в XSLT

Q: Потребовалось тут немного xml/xsl вспомнить, а точнее, изучить новые возможности современного XML. Задачка класическая: написать xsl для конвертирования xml-ля в text, html, rtf, pdf.

Ну, с html более-менее понятно, а вот для text и rtf вопросы возникли (sorry, если вдруг что то из faq проскочило)

PLAIN TEXT форматирование:

как обозначить перевод строки?

A: &#xA;

...

Q: как ограничить длину всех строк в тексте "максимум 80 символов"?

A: Ох, непросто. Не тем концом отвертки гвозди забиваете. Можно написать рекурсивный шаблон, которому передаются два параметра: текущая длина строки и остаток строки. Шаблон берет первый токен остатка строки, отделенный пробелами, складывает его длину с текущей длиной строки плюс один и сравнивает с 80. Если больше, то выводит &#xA;, и вызывает сам себя с текущей длиной строки равной 0 и тем же остатком строки. Если меньше, то выводит пробел, затем первый токен остатка строки и вызывает себя с новой текущей длиной строки равной старой текущей длине строки плюс длина первого токена текущего остатка строки плюс единица и с новым остатком строки равным части старого текущего остатка после пробела после первого токена старого текущего остатка строки.

Однако, как очевидно из вышесказанного, это есть извращение. Легче написать либо расширение, либо простенький фильтр.

XSLT слабо подходит для форматирования текста.

Q: как сделать, чтобы первые буквы стали заглавными?

Тоже непросто. Описывать рекурсивную функцию и как ее писать я не буду, <бессовестная-самореклама>посмотри в моей книжке по XSLT, там про рекурсии есть</бесовестная самореклама>. Строчные/прописные буквы можно друг на друга заменять при помощи функции translate, <бессовестная-самореклама>опять же, пример функции в книжке есть</бесовестная самореклама>.

Но, честное слово, подыщи для форматирования текста другой инструмент. XSLT работает со структурой документа.

Q: HTML форматирование:

как обозначить пробел не самим пробелом, а &nbsp, например? (сам по себе &nbsp;, конечно же, не проходит)

A: Пиши &#xA0;. Это неразрываемый пробел в Unicode. Большинство нормальных процессоров при методе html выводят его как &nbsp;.

-- Aleksei Valikov в fido7.ru.xml

Разница между "current()" и "."

Q: Как я понял, это не совсем аналогичные вещи, запрос "item[@value=current()/@id]" не будет равным "item[@value=./@id]". Есть еще аналог current()?

A: функция current() возвращает текущий узел. Когда выполняется шаблон, или тело оператора xsl:for-each, всегда есть один узел, с которого начинается вычисление относительных путей XPath, этот узел и называется "текущим" и возвращается функцией current().

Выражение "." -- это сокращение для "self::node()", т.е. для контекстного узла.

Разница между ними в том, что при навигации по осям XPath значение контекстного узла изменяется, значение current() -- нет.

-- Sergey Groznyh в fido7.ru.xml, 2002-12-18 10:27:02

Многоязычность в XSLT

О создании языкозависимых XSLT-преобразований: http://xmlhack.ru/articles/02/11/09/langsubst.html

Language support in the DocBook XSL stylesheets: http://www.sagehill.net/docbookxsl/Localizations.html

MSXML: не работает XSLT

Вопрос

У меня не работают (или неправильно работают) XSLT-преобразования. Использую MSXML. В чем дело?

Ответ

Скорее всего, используется старая версия MSXML. Типичные симптомы:

Если наблюдается что-либо похожее, значит, используется старая версия MSXML. Пространство имён TR/WD-xsl соответствует раннему драфту XSLT, который не совместим со стандартом языка XSLT, но до сих пор широко используется Microsoft. Чтобы пользоваться "нормальным" XSLT в MSXML, надо обновить версию:

Вопрос

Я поставил новую версию MSXML, но всё равно ничего не работает!

Ответ

Как было сказано выше, старая версия языка широко используется в решениях Microsoft, поэтому в новых версиях MSXML от WD-xsl не отказались. По умолчанию MSXML ставится в так называемом side-by-side mode, при котором апдейт XSLT не касается, к примеру, MSIE. Чтобы использовать нормальный XSLT нужно ставить в replace-mode. Вот маленькая утилика, которая все делает как надо: http://www.msdn.microsoft.com/code/default.asp?url=/code/sample.asp?url=/msdn-files/027/001/469/msdncompositedoc.xml

Также см. http://www.netcrucible.com/xslt/msxml-faq.htm

MSXML: не работает XPath

Используется XMLDOMDocument. Простые XPath-выражения работают. Если же использовать функции (contains, string-length, ...) или сложные выражения, то запрос не отрабатывает. Почему?

MSXML DOM поддерживает два языка запроса: обычный XPath и более простой XSLPattern. По умолчанию используется XSLPattern.

Переключение на XPath и дополнительные сведения описаны в базе знаний MSDN: "How To Use XPath Queries in MSXML DOM selectNodes Method" (Article ID 288913).

PHP и XML

Форум PHPClub «PHP + XML + XSLT + XSL»: http://phpclub.net/talk/forumdisplay.php?forumid=16

Как прервать SAX-парсер

Q: (Java) Есть такая вводная: имеется большой xml-файл, из которого информации нам требуется чуть, да и то она вся там в начале находится. И как водится, натравляю я на него SAX-анализатор с целью эту ценную инфу добыть. И вот, когда казалось бы, что победа уже близка и инфа добыта, наступает черед горького разочарования: парсер продолжает анализировать файл :(

В итоге вопрос к знатокам: как прервать ручками анализ файла?

Пока ничего, кроме засовывания анализа в отдельный поток и его терминирования, в голову не приходит....

A: Я в подобных ситуациях поступаю так:

public class StopException extends SAXException {}

...
[code]
throw new StopException();
[/code]

..

try {  reader.parse(src); }
catch (StopException e) {}

-- Nikolai Grigoriev в fido7.ru.xml

URL содержит &amp; вместо &

Q: В результате XSLT-преобразования получается

 <img src="counter.png?x=7&amp;y=17 />,

а нужно

 <img src="counter.png?x=7&y=17 />.

Что делать?

Q: Пишу в xhtml-файле

 <img src="counter.png?x=7&y=17 />,

а валидатор ругается, говорит, что entity y undefined или expecting ';'. Что делать?

A: Ответ: в обоих случаях правильный вариант

 <img src="counter.png?x=7&amp;y=17 />.

Обозреватели правильно понимают URL, записанный в таком виде.

Русские буквы в URL превращаются в %xx%xx%xx...

Q: В результате XSLT-преобразования атрибуты a/@href вместо русских букв содержат коды. Например, вместо

 <a href="ссылка">ссылка</a>

получается

 <a href="%d1%81%d1%81%d1%8b%d0%bb%d0%ba%d0%b0">ссылка</a>

В других атрибутах (не a/@href) всё ok. что тут можно сделать?

A: Никогда не используйте русские буквы в URL. С ними всегда только проблемы.

В данном случае ничего делать не надо, всё работает правильно. Результат корректен как с точки зрения стандарта, так и с точки зрения браузера.

В соответствии со спецификацией XSLT (глава “16.2 HTML Output Method”):

The html output method should escape non-ASCII characters in URI attribute values using the method recommended in Section B.2.1 of the HTML 4.0 Recommendation

Из HTML 4.0 Recommendation:

We recommend that user agents adopt the following convention for handling non-ASCII characters in such cases:
1. Represent each character in UTF-8 (see [RFC2279]) as one or more bytes.
2. Escape these bytes with the URI escaping mechanism (i.e., by converting each byte to %HH, where HH is the hexadecimal notation of the byte value).
This procedure results in a syntactically legal URI (as defined in [RFC1738], section 2.2 or [RFC2141], section 2) that is independent of the character encoding to which the HTML document carrying the URI may have been transcoded.

Неразрывный пробел (&nbsp;)

Q: Есть XML и XSLT, на выходе получаю HTML, но не могу придумать, как вставлять &nbsp;, так как если записать просто, то libxslt ругается на него, а если написать &amp;nbsp;, то получу слово nbsp.

A: Проблема более общая, и XSLT здесь не при чём. XML-парсер не знает, что такое &nbsp; и выдаёт ошибку.

Вместо &nbsp; можно писать &#xA0; или &#160;

Если же очень хочется писать именно &nbsp;, то нужно предварительно определить эту сущность:

<?xml version="1.0" encoding="koi8-r/windows-1251/etc"?>
<!DOCTYPE article [
<!ENTITY nbsp "&#xa0;">
]>
<article>
<p>Неразрывный&nbsp;пробел.</p>
</article>

Для XSLT есть неправильное антирешение, которое не рекомендуется использовать:

<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>

Символ "неразрывный пробел"

уже давным давно есть нормальный UNICODE символ "неразрывный пробел".

&#160;, или, что одно и то же &#xA0; (см. выше)

© 2001-2007 xmlhack.ru. RSS 0.91, 1.0, ЖЖ (LJ). Для писем: info@.