Как сопоставить и обработать неизвестные XML-элементы в XSLT 1.0?

#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. Можно также явно установить приоритеты шаблона вместо неявного по порядку документов (чтобы избежать!) или по специфике.