2015-06-08 5 views
0

Я использую tagsoup как (SAX) XMLREader и задаю функцию пространства имен false. Этот синтаксический анализатор используется для подачи Transformer в качестве источника SAX. Полный код:Как сделать преобразование XSL в Java, используя парсер, не содержащий имен пространства имен?

final TransformerFactory factory = TransformerFactory.newInstance(); 
    final Transformer t = factory.newTransformer(new StreamSource(
     getClass().getResourceAsStream("/identity.xsl"))); 

    final XMLReader p = new Parser(); // the tagsoup parser 
    p.setFeature("http://xml.org/sax/features/namespaces", false); 

    // getHtml() returns HTML as InputStream 
    final Source source = new SAXSource(p, new InputSource(getHtml())); 

    t.transform(source, new StreamResult(System.out)); 

Это приводит к чему-то вроде:

< xmlns:html="http://www.w3.org/1999/xhtml"> 
<> 
<> 
<> 
<> 
< height="17" valign="top"> 

Проблема заключается в том, что имена тегов являются пустыми. XMLReader (tagoup parser) сообщает о пустом пространстве именURI и пустом локальном имени в методах SAX ContentHandler#startElement и ContentHandler#endElement. Для анализатора, не содержащего пространства имен, это разрешено (см. Javadoc).

Если я добавлю XMLFilter, который копирует значение qName в localName, все будет хорошо. Однако это не то, что я хочу, я ожидаю, что это будет работать «из коробки». Что я делаю не так? Любой вход был бы оценен!

+0

Зачем вам нужно использовать XSLT с XmlReader, который не поддерживает пространства имен? Известно, что XSLT/XPath требует корректного ввода пространства имен. –

+0

Если пространства имен разрешены, мне нужны выражения xpath, такие как 'h: html/h: body/h: table/h: tbody/h: tr' вместо' html/body/table/tbody/tr' (короткий ответ: потому что я ленив и/или мои знания xslt сосет). – rmuller

+0

Обратите внимание, что в TagSoup в соответствии с http://home.ccil.org/~cowan/tagsoup/#program есть опция '--nons' для подавления пространств имен (пространство имен подавляется.). Я бы предположил, что вы можете включить это, используя свой API, и в этом случае, когда вы анализируете HTML, элементы, о которых идет речь, не должны содержать пространства имен (которое может обрабатывать XSLT/XPath). –

ответ

0

Я ожидаю, что это будет работать «из коробки». Что я делаю не так?

Что вы делаете неправильно, это технология (XSLT), которая определена для работы с XML-форматом, хорошо проработанным в пространстве имен, и пытается применить его к данным, с которыми он не предназначен. Если вы хотите использовать XSLT, то вы должны указать : включить пространства имен, объявить префикс для пространства имен http://www.w3.org/1999/xhtml в вашей таблице стилей и последовательно использовать этот префикс в выражениях XPath.

Если трансформатор понимает XSLT 2.0 (например, Saxon 9), то вместо того, чтобы объявить префикс и предваряя ваши имена элементов в XPath выражений, вы можете положить xpath-default-namespace="http://www.w3.org/1999/xhtml" на xsl:stylesheet элемент, чтобы сделать его лечить префиксов имен элементов, как ссылки на это пространство имен. Но в XSLT 1.0 (по умолчанию встроенная реализация Java Transformer) единственным вариантом является использование префикса.

+0

Очень чистый ответ! Для меня недостающее звено было: Если вы хотите использовать XSLT, тогда вы должны включить пространства имен ** во входном документе **. Я знаю о функции XSLT 2, но для этого проекта доступен только XSLT 1, и я действительно ненавижу использовать префиксы снова и снова, поэтому отключение пространств имен на входном документе должно быть умным :) – rmuller

+0

В качестве дополнения : Я не могу найти упоминание в Javadoc об этом предварительном условии! – rmuller