Используя xslt, преобразуйте один XML-документ на основе содержимого второго XML-документа.
Вопрос
У меня есть один набор документов, которые неявно определяют разрешенные поля для второго набора объектов, которые должны быть преобразованы в третий набор документов ( какие "правила" используемый документ зависит от содержимого преобразуемого файла), например Р>
<!-- One example rules document -->
<document object="obj1_rules">
<field name="A"/>
<field name="B"/>
<field name="C"/>
</document>
<!-- Document to be tranformed based upon obj1_rules-->
<document object="obj1">
<field name="A"/>
<field name="B"/>
<field name="C"/>
<field name="D"/>
<field name="E"/>
</document>
<!-- Desired result-->
<document object="obj1">
<newfield name="A"/>
<newfield name="B"/>
<newfield name="C"/>
</document>
Возможно ли сделать это преобразование с помощью xslt?
Я вижу, что " в XSLT нет способа создания выражений XPath (например, ссылки на переменные) во время выполнения. " Итак, мне не повезло, или я просто смотрю на эту проблему неправильно? Спасибо!
Решение
Вот простое решение :
Это преобразование .
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- -->
<xsl:variable name="vrtfRules">
<document object="obj1_rules">
<field name="A"/>
<field name="B"/>
<field name="C"/>
</document>
</xsl:variable>
<!-- -->
<xsl:variable name="vRules" select=
"document('')/*/xsl:variable
[@name = 'vrtfRules']
/*
"/>
<!-- -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- -->
<xsl:template match="field">
<xsl:if test="@name = $vRules/*/@name">
<newfield>
<xsl:apply-templates select="node()|@*"/>
</newfield>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
при применении к оригинальному исходному XML-документу:
<document object="obj1">
<field name="A"/>
<field name="B"/>
<field name="C"/>
<field name="D"/>
<field name="E"/>
</document>
дает желаемый результат:
<document object="obj1">
<newfield name="A"/>
<newfield name="B"/>
<newfield name="C"/>
</document>
Обратите внимание , что " документ о правилах " находится в таблице стилей только для компактности. Когда это отдельный документ, просто document () Используемая функция code>
должна быть скорректирована с учетом фактического href
.
Другие советы
Возможно, я упрощаю, но есть ли причина, по которой ваш " документ о правилах " не может быть просто XSLT?
Хорошо, я понимаю, почему вы хотите иметь правила в простом xml-файле, а не в полноценной таблице стилей xsl, но вы просто пропускаете шаг.
Вам нужно создать таблицу стилей xsl, которая преобразует документ правила xml в таблицу стилей xsl, которую вы затем примените к исходному XML.
Хитрость заключается в том, что пространства имен не должны путаться из-за сочетания примененных правил xsl и сгенерированных правил xsl.
<?xml version="1.0" ?> <xsl:stylesheet xmlns="YOUR_NAMESPACE_HERE" xmlns:output="http://www.w3.org/1999/XSL/Transform" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="xml" indent="yes" media-type="text/xsl" /> <xsl:template match="/"> <output:stylesheet version="2.0"> <xsl:apply-templates /> </output:stylesheet> </xsl:template> <xsl:template match="document[@object]"> <output:template match="document[@object='{@object}']"> <output:copy> <xsl:apply-templates /> </output:copy> </output:template> </xsl:template> <xsl:template match="field[@name]"> <output:if test="field[@name='{@name}']"> <output:copy-of select="field[@name='{@name}']" /> </output:if> </xsl:template> </xsl:stylesheet>
Я предполагал, что вы будете использовать один и тот же атрибут объекта документа в правилах и в самих документах (это намного проще, imo).
Итак, вы управляете своим документом правил через таблицу стилей выше. В результате получается новая таблица стилей xsl, которая в точности соответствует тому, что вы описываете в своем документе правила xml. Затем вы применяете эту результирующую таблицу стилей к исходному документу, и вы должны получить ожидаемый результат.