The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Локализация XML при использовании Saxon. (xml rus locale xslt)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: xml, rus, locale, xslt,  (найти похожие документы)
Date: Tue, 05 Nov 2002 14:38:10 +0500 From: Aleksei Valikov <valikov@fzi.de> Newsgroups: ftn.ru.xml Subject: Локализация XML при использовании Saxon. Проблема локализации обсуждалась не раз. Поскольку многие используют Saxon, могу рассказать о довольно эффективном решении на Saxon. Локализация фактически в том, что языкозависимые ресурсы запихиваются в ResourceBundle, а доступ к ним происходит по ключам. Довольно неплохо сделана локализация в JSTL. <fmt:message key="message_key"/> заменится на значение ключа, взятого из пакета ресурсов. Похожий метод можно применить в XSLT. Вместо Welcome писать <fmt:message key="welcome"/> а на выходе должно получаться Welcome, Wilkommen или что там еще указано. В атрибутах можно писать например так: <b a="{fmt:message('welcome')}"/> Тогда локализация фактически сводится к фильтрации создаваемого документа. Можно, конечно, дополнительным преобразованием фильтровать все эти элементы и атрибуты, но это неэффективно. Лучше всего фильтровать поток SAX-событий. В JAXP это, если честно, по-человечески не делается. Потому как если SAXResult или DOMResult, то это ладно, это можно фильтровать, а если StreamResult (самый частый случай)? Тогда фильтрованный поток придется сериализовать, а как это сделать без output properties трансформера? Приходится делать SAXResult, которому сообщать параметры сериализации... А еще если трансформера в явном виде нет (x-тэги в JSTL). Короче, очень неудобно/ В Saxon в качестве Result можно использовать эмиттеры. Эмиттеры отличаются от результатов тем, что эмиттерам Saxon сообщает больше информации - например, output properties. То есть можно написать прокси эмиттер, который по output properties сам себе создаст соответствующий сериализатор и будет только фильтровать нужные элементы и атрибуты. Вот как примерно выглядит фильтрация: public void startElement( int nameCode, Attributes attributes, int[] namespaces, int nscount) throws TransformerException { String uri; String localName; if (nameCode == lastNameCode) { uri = lastURI; localName = lastLocalName; } else { uri = namePool.getURI(nameCode); localName = namePool.getLocalName(nameCode); lastNameCode = nameCode; lastURI = uri; lastLocalName = localName; } if (namespaceURI.equals(uri) && "message".equals(localName)) { final String key = attributes.getValue("key"); final String value = getResourceString(key); baseEmitter.characters(value.toCharArray(), 0, value.length()); } else { boolean f = false; Attributes newAttributes = attributes; AttributesImpl ai = null; for (int i = 0; i < attributes.getLength(); i++) { final String value = attributes.getValue(i); if (value.startsWith("{fmt:message(\'") && value.endsWith("\')}")) { if (!f) { ai = new AttributesImpl(); newAttributes = ai; for (int j = 0; j < i; j++) { ai.addAttribute( attributes.getURI(j), attributes.getLocalName(j), attributes.getQName(j), attributes.getType(j), attributes.getValue(j)); } f = true; } final String key = value.substring(value.indexOf('\'') + 1, value.lastIndexOf('\'')); ai.addAttribute( attributes.getURI(i), attributes.getLocalName(i), attributes.getQName(i), attributes.getType(i), getResourceString(key)); } } super.startElement(nameCode, newAttributes, namespaces, nscount); } } public void endElement(int nameCode) throws TransformerException { String uri; String localName; if (nameCode == lastNameCode) { uri = lastURI; localName = lastLocalName; } else { uri = namePool.getURI(nameCode); localName = namePool.getLocalName(nameCode); lastNameCode = nameCode; lastURI = uri; lastLocalName = localName; } if (namespaceURI.equals(uri) && "message".equals(localName)) { // do nothing } else super.endElement(nameCode); } Создание сериализатора свиснуто из GeneralOutputter из Saxon: public void createUnderlyingEmitter() { Emitter emitter = null; final String method = outputProperties.getProperty(OutputKeys.METHOD); if (method == null) { emitter = new UncommittedEmitter(); } else if (method.equals("html")) { emitter = new HTMLEmitter(); if (!"no".equals(outputProperties.getProperty(OutputKeys.INDENT))) { HTMLIndenter in = new HTMLIndenter(); in.setUnderlyingEmitter(emitter); emitter = in; } } else if (method.equals("xml")) { emitter = new XMLEmitter(); if ("yes".equals(outputProperties.getProperty(OutputKeys.INDENT))) { XMLIndenter in = new XMLIndenter(); in.setUnderlyingEmitter(emitter); emitter = in; } String cdataElements = outputProperties.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS); if (cdataElements != null && cdataElements.length() > 0) { CDATAFilter filter = new CDATAFilter(); filter.setUnderlyingEmitter(emitter); emitter = filter; } } else if (method.equals("text")) { emitter = new TEXTEmitter(); } else { // TODO: externally supplied properties must be validated int brace = method.indexOf('}'); String localName = method.substring(brace + 1); int colon = localName.indexOf(':'); localName = localName.substring(colon + 1); /*if (localName.equals("fop")) { // avoid an explicit external reference to avoid build problems // when FOP is not present on the class path emitter = Emitter.makeEmitter("com.icl.saxon.fop.FOPEmitter"); } else */ if (localName.equals("xhtml")) { emitter = new XHTMLEmitter(); if ("yes".equals(outputProperties.getProperty(OutputKeys.INDENT))) { HTMLIndenter in = new HTMLIndenter(); in.setUnderlyingEmitter(emitter); emitter = in; } String cdataElements = outputProperties.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS); if (cdataElements != null && cdataElements.length() > 0) { CDATAFilter filter = new CDATAFilter(); filter.setUnderlyingEmitter(emitter); emitter = filter; } } /*else { emitter = Emitter.makeEmitter(localName); }*/ } setUnderlyingEmitter(emitter); } Метод получения строки из пакета ресурсов тривиален: public String getResourceString(final String key) { if (key == null || resourceBundle == null) return "????"; else { try { final String value = resourceBundle.getString(key); if (value == null) throw new NullPointerException(); return value; } catch (Exception e) { return "??" + key + "??"; } } } Примерно вот так. Я допричесываю этот код, включу в xml.transform. Hадо будет еще custom tag написать под это дело. Комментарии, критика welcome. -- Все об XSLT в книге "Технология XSLT". Сайт издательства http://www.bhv.ru/cgi-bin/bhv.exe/card?isbn=5-94157-129-1 Books.ru http://www.books.ru/shop/books/22090

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ RSS ]
  • 1, cosette (?), 17:52, 16/12/2014 [ответить]  
  • +/
    Если Вы заинтересованы в локализации web-ПО, ПО для персональных компьютеров, ПО для мобильных устройств либо иного вида программного обеспечения, я рекомендую Вам использовать этот инструмент на базе web: https://poeditor.com/
     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру