#java #preprocessor #xslt-1.0
#java #препроцессор #xslt-1.0
Вопрос:
У меня есть таблица стилей simply XSLT 1.0, которая преобразует XML-документы в XHTML. Я действительно хочу иметь возможность «включать» содержимое XML-файла в другой, когда это необходимо. AFAIK, это просто невозможно в XSLT 1.0, поэтому я решил перенести свою обработку в простое Java-приложение, которое предварительно обработало бы XML, рекурсивно выполнив «includes» и передав его на XSLT-процессор JDK по умолчанию. У меня есть XML-схема, которой должны соответствовать мои документы.
Наиболее используемый элемент называется «text» и может иметь атрибут «id» и / или «class», который используется для оформления XHTML с помощью CSS. Этот элемент преобразуется в «p», «div» или «span» в зависимости от контекста.
Что я хотел бы добавить, так это возможность определять «неизвестные» элементы в моих входных файлах и преобразовывать их в «текстовый» элемент для дальнейшей обработки. Если название «неизвестного» элемента начинается с заглавной буквы, то оно становится «текстовым», а «id» присваивается исходному имени. В противном случае «текст» с «классом», присвоенным исходному имени. Все остальное в неизвестном элементе должно быть сохранено как есть, а затем оно должно быть обработано XSLT, как если бы оно изначально было во входном файле. Другими словами, я хотел бы преобразовать все неизвестные элементы в допустимый XML-документ, а затем обработать его с помощью моей таблицы стилей.
Можно ли это сделать в XSLT, возможно, в «таблице стилей» предварительной обработки, или я должен сделать это как предварительную обработку в Java? Производительность здесь не важна. Я бы предпочел решение на XSLT, но не в том случае, если это намного сложнее, чем делать это на Java.
Ответ №1:
Что ж, поскольку никто не ответил, я просто попробовал это. Хотя это проще сделать на Java, у этого есть один существенный недостаток: поскольку коду необходимо знать допустимые элементы, чтобы он распознавал неизвестные, вам в конечном итоге придется жестко закодировать это в своем коде и перекомпилировать его, если шаблон XSLT изменится.
Итак, я попробовал в XSLT, и это тоже работает. Допустим, у вас есть:
<xsl:template match="text">
*processing*
<xsl:call-template name="id_and_class"/>
*processing*
</xsl:template>
если шаблон с именем id_and_class копирует ваш идентификатор и атрибут classes в сгенерированном элементе, и вы хотите, чтобы неизвестные элементы были сопоставлены с элементами «text», тогда вы можете сделать это:
<xsl:template match="text">
<xsl:call-template name="text_processing"/>
</xsl:template>
<xsl:template name="text_processing">
*processing*
<xsl:call-template name="text_id_and_class"/>
*processing*
</xsl:template>
...
<xsl:template name="text_id_and_class">
<xsl:choose>
<!-- If name() is not "text", then we have an unknown element. -->
<xsl:when test="name()!='text'">
<!-- Processing of ID and class omitted ... -->
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="id_and_class"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
...
<!-- MUST BE LAST : Process unknown elements like a "text" element. -->
<xsl:template match="*">
<xsl:call-template name="text_processing"/>
</xsl:template>
Если вы обрабатываете содержимое одного конкретного элемента с помощью именованного шаблона, то вы можете проверить в этом шаблоне, совпадает ли имя, и использовать это для вашей специальной обработки. Тогда вам просто нужно поместить <xsl:template match=»*»> в конец вашей таблицы стилей и вызвать именованный шаблон оттуда.
Комментарии:
1. Можно также явно установить приоритеты шаблона вместо неявного по порядку документов (чтобы избежать!) или по специфике.