Вопрос или проблема
Я не знаю слов для того, что хочу достичь, поэтому постараюсь объяснить как можно лучше. Не стесняйтесь перенаправить меня на существующие вопросы.
Допустим, у меня есть XML файл, содержащий список классов (названный index.xml
):
<root>
<classes>
<class>
<id>ClassA</id>
</class>
<class>
<id>ClassB</id>
</class>
<class>
<id>ClassC</id>
</class>
</classes>
</root>
И у меня есть в другом XML файле некоторые детали свойств:
<root>
<properties>
<property>
<name>MyPropertyA</name>
<type>ClassA</type>
</property>
<property>
<name>MyPropertyB</name>
<type>ClassB</type>
</property>
<property>
<name>MyPropertyE</name>
<type>ClassE</type>
</property>
</properties>
</root>
Я хотел бы иметь селектор для apply-templates
на свойствах только в том случае, если их type
содержится в узле classes
файла index.xml
.
Я думаю, что мне нужно сослаться на index.xml
с помощью функции document()
и использовать функцию key()
для поиска в classes
, но, похоже, мне не удается собрать эти части вместе, чтобы достичь своей цели…
Я пробовал что-то подобное, но это не работает:
<xsl:variable name="ClassLookup" select="document('index.xml')/classes"/>
<xsl:apply-template match="property[key(ClassLookup, ./type)]">
Любая помощь приветствуется.
Без ключа вы бы использовали <xsl:apply-template match="property[type = document('index.xml')/classes/class/id]">
.
Использовать ключ с вторичными документами легко в XSLT 2 и более поздних версиях, поэтому сначала укажите, какую версию вы используете, чтобы мы могли сказать, насколько легко использовать ключ.
Ответ или решение
Применение XSLT для фильтрации узлов на основе внешнего XML файла
В этой статье мы рассмотрим, как использовать XSLT для фильтрации узлов в XML файле на основе значений из другого XML файла. Это может быть полезным в случаях, когда ваши данные имеют обозначенные классы, и вы хотите обрабатывать свойства только тех классов, которые есть в вашем индексе классов.
Исходные данные
У нас есть два XML файла:
- index.xml – содержит список классов:
<root>
<classes>
<class>
<id>ClassA</id>
</class>
<class>
<id>ClassB</id>
</class>
<class>
<id>ClassC</id>
</class>
</classes>
</root>
- properties.xml – содержит свойства, которые могут быть связаны с классами:
<root>
<properties>
<property>
<name>MyPropertyA</name>
<type>ClassA</type>
</property>
<property>
<name>MyPropertyB</name>
<type>ClassB</type>
</property>
<property>
<name>MyPropertyE</name>
<type>ClassE</type>
</property>
</properties>
</root>
Цель
Наша цель заключается в том, чтобы применить шаблон (используя <xsl:apply-templates>
) к элементам property
из файла properties.xml
, если поле type
соответствует одному из классов в файле index.xml
.
Решение
Для достижения этой цели мы можем использовать функцию document()
для загрузки index.xml
, а также key()
для поиска классов. Если вы используете XSLT 2.0 или 3.0, использование ключей облегчит процесс фильтрации.
Шаг 1: Определение ключа
Для начала определим ключ в вашем XSLT, который извлечет идентификаторы классов из index.xml
.
<xsl:key name="classKey" match="class" use="id" />
Шаг 2: Применение шаблонов
Теперь мы можем написать выражение для применения шаблонов только к тем свойствам, тип которых есть в нашем индексе классов.
<xsl:apply-templates select="property[key('classKey', type)]"/>
Полный XSLT пример
Ниже приведен полный пример XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="classes" select="document('index.xml')/root/classes"/>
<!-- Определяем ключи для идентификации классов -->
<xsl:key name="classKey" match="class" use="id"/>
<xsl:template match="/root">
<properties>
<!-- Применяем шаблоны только к тем свойствам, у которых тип соответствует классу из index.xml -->
<xsl:apply-templates select="properties/property[key('classKey', type)]"/>
</properties>
</xsl:template>
<xsl:template match="property">
<outputProperty>
<name><xsl:value-of select="name"/></name>
<type><xsl:value-of select="type"/></type>
</outputProperty>
</xsl:template>
</xsl:stylesheet>
Заключение
Используя функции document()
и key()
, мы можем эффективно фильтровать узлы в одном XML документе на основе значений из другого документа. Это решение позволяет обрабатывать данные более целенаправленно и организованно. Надеюсь, это объяснение поможет вам в ваших начинаниях с XSLT и манипуляцией XML файлами. Если у вас возникли дополнительные вопросы, не стесняйтесь задавать их!