Как использовать функцию встроенного каталога saxon

Я скачал SaxonHE9-4-0-6J и хочу обработать XHTML на CLI. Однако Саксон пытается загрузить DTD из W3C, и на каждую простую команду уходит слишком много времени.

У меня есть каталог XML, который я успешно использую с xmllint, установив переменную env, указывающую на файл каталога, но я понятия не имею, как заставить Saxon использовать его. Google раскрывает всю историю изменений (таким образом, путаницу) в отношении использования каталогов с Saxon, и ни одно из них не порадовало меня.

Я скачал resolver.jar и установил его в CLASSPATH, но я не могу заставить Саксона использовать его. После различных комбинаций я следил за http://www.saxonica.com/documentation/sourcedocs/xml-catalogs.xml, используя только переменную каталога, например:

-catalog:path-to-my-catalog

(пробовал как URI, так и обычные пути) и без настройки -r, -x, -y переключается, но Саксон не видит этого. Я получаю эту ошибку:

Ошибка обработки запроса: не удалось загрузить библиотеку распознавателя каталога Apache

resolver.jar установлен в моем classpath, и я могу использовать его из командной строки:

C:\temp>java org.apache.xml.resolver.apps.resolver
Usage: resolver [options] keyword

Where:

-c catalogfile  Loads a particular catalog file.
-n name         Sets the name.
-p publicId     Sets the public identifier.
-s systemId     Sets the system identifier.
-a              Makes the system URI absolute before resolution
-u uri          Sets the URI.
-d integer      Set the debug level.
keyword         Identifies the type of resolution to perform:
                doctype, document, entity, notation, public, system,
                or uri.

OTOH, сам архив Saxon уже включает в себя XHTML и различные другие DTD, поэтому из этого разочарования должен быть простой выход.

Как использовать Saxon в командной строке и проинструктировать его использовать локальные DTD?

2 ответа

Решение

Из ссылки на саксонику в вашем вопросе:

Когда в командной строке используется опция -catalog, это переопределяет внутренний распознаватель, используемый в Saxon (начиная с 9.4), для перенаправления известных ссылок W3C (таких как XHTML DTD) на локальные копии этих ресурсов Saxon. Поскольку обе эти функции основаны на настройке EntityResolver анализатора XML, их невозможно использовать совместно.

Для меня это звучит так, как будто Saxon автоматически использует локальные копии известных DTD для W3C, но если вы укажете -catalog, он не использует внутренний распознаватель, и вы должны явно указать их в своем каталоге.


Вот рабочий пример использования каталога с саксонским...

Структура файла / каталога моего примера

C:/so_test/lib
C:/so_test/lib/catalog.xml
C:/so_test/lib/resolver.jar
C:/so_test/lib/saxon9he.jar
C:/so_test/lib/test.dtd
C:/so_test/test.xml

XML DTD (so_test/lib/test.dtd)

<!ELEMENT test (foo)>
<!ELEMENT foo (#PCDATA)>

XML-экземпляр (so_test/test.xml)

Обратите внимание, что системный идентификатор указывает на несуществующее местоположение, чтобы убедиться, что каталог используется.

<!DOCTYPE test PUBLIC "-//TEST//Dan Test//EN" "dir_that_doesnt_exist/test.dtd">
<test>
    <foo>Success!</foo>
</test>

Каталог XML (so_test/lib/catalog.xml)

<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
    <group prefer="public" xml:base="file:///C:/so_test/lib">
        <public publicId="-//TEST//Dan Test//EN" uri="lib/test.dtd"/>
    </group>
</catalog>

Командная строка

Обратите внимание -dtd возможность включить проверку.

C:\so_test>java -cp lib/saxon9he.jar;lib/resolver.jar net.sf.saxon.Query -s:"test.xml" -qs:"<results>{data(/test/foo)}</results>" -catalog:"lib/catalog.xml" -dtd

Результаты

<results>Success!</results>

Если я сделаю экземпляр XML недействительным:

<!DOCTYPE test PUBLIC "-//TEST//Dan Test//EN" "dir_that_doesnt_exist/test.dtd">
<test>
    <x/>
    <foo>Success!</foo>
</test>

и запустите ту же командную строку, что и выше, вот результат:

Recoverable error on line 4 column 6 of test.xml:
  SXXP0003: Error reported by XML parser: Element type "x" must be declared.
Recoverable error on line 6 column 8 of test.xml:
  SXXP0003: Error reported by XML parser: The content of element type "test" must match "(foo)".
Query processing failed: The XML parser reported two validation errors

Надеемся, что этот пример поможет вам понять, что изменить в вашей настройке.

Кроме того, используя -t опция дает вам дополнительную информацию, например, какой каталог был загружен и был ли разрешен открытый идентификатор:

Loading catalog: file:///C:/so_test/lib/catalog.xml
Saxon-HE 9.4.0.6J from Saxonica
Java version 1.6.0_35
Analyzing query from {<results>{data(/test/foo)}</results>}
Analysis time: 122.70132 milliseconds
Processing file:/C:/so_test/test.xml
Using parser org.apache.xml.resolver.tools.ResolvingXMLReader
Building tree for file:/C:/so_test/test.xml using class net.sf.saxon.tree.tiny.TinyBuilder
Resolved public: -//TEST//Dan Test//EN
        file:/C:/so_test/lib/test.dtd
Tree built in 0 milliseconds
Tree size: 5 nodes, 8 characters, 0 attributes
<?xml version="1.0" encoding="UTF-8"?><results>Success!</results>Execution time: 19.482079ms
Memory used: 20648808

Дополнительная информация

Saxon распространяет версию Xerces для Apache, поэтому используйте resolver.jar находится в дистрибутиве Apache Xerces.

Даниэль Хейли ответил лучше, чем я, о том, как использовать явный каталог с Saxon.

Что касается использования встроенных копий известных DTD, Saxon 9.4 действительно сделает это автоматически по умолчанию, если он распознает системный идентификатор или открытый идентификатор требуемого ресурса. Если он идет на сайт W3C, первое, что нам нужно выяснить, - это точная форма используемого DOCTYPE.

Сообщение об ошибке при сбое загрузки распознавателя каталога Apache фактически означает, что Saxon не удалось загрузить класс org.apache.xml.resolver.CatalogManager. Интересно, используете ли вы версию распознавателя, которая не включает этот класс? Я не могу придумать другого объяснения.

Другие вопросы по тегам