Вот мой надуманный пример, который иллюстрирует то, что я пытаюсь достичь.У меня есть входной XML-файл, который я хочу сгладить для дальнейшей обработки.
Входной файл:
<BICYCLES>
<BICYCLE>
<COLOR>BLUE</COLOR>
<WHEELS>
<WHEEL>
<WHEEL_TYPE>FRONT</WHEEL_TYPE>
<FLAT>NO</FLAT>
<REFLECTORS>
<REFLECTOR>
<REFLECTOR_NUM>1</REFLECTOR_NUM>
<SHAPE>SQUARE</SHAPE>
</REFLECTOR>
<REFLECTOR>
<REFLECTOR_NUM>2</REFLECTOR_NUM>
<SHAPE>ROUND</SHAPE>
</REFLECTOR>
</REFLECTORS>
</WHEEL>
<WHEEL>
<WHEEL_TYPE>REAR</WHEEL_TYPE>
<FLAT>NO</FLAT>
</WHEEL>
</WHEELS>
</BICYCLE>
</BICYCLES>
Входные данные представляют собой список <BICYCLE>
узлов.Каждый <BICYCLE>
имеет <COLOR>
и опционально имеет <WHEELS>
.
<WHEELS>
- это список <WHEEL>
узлов, каждый из которых имеет несколько атрибутов и, необязательно, имеет <REFLECTORS>
.
<REFLECTORS>
- это список <REFLECTOR>
узловкаждый из которых имеет несколько атрибутов.
Цель состоит в том, чтобы сгладить этот XML.Это XSL, который я использую:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" xml:space="preserve"/>
<xsl:template match="/">
<BICYCLES>
<xsl:apply-templates/>
</BICYCLES>
</xsl:template>
<xsl:template match="BICYCLE">
<xsl:choose>
<xsl:when test="WHEELS">
<xsl:apply-templates select="WHEELS"/>
</xsl:when>
<xsl:otherwise>
<BICYCLE>
<COLOR><xsl:value-of select="COLOR"/></COLOR>
<WHEEL_TYPE/>
<FLAT/>
<REFLECTOR_NUM/>
<SHAPE/>
</BICYCLE>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="WHEELS">
<xsl:apply-templates select="WHEEL"/>
</xsl:template>
<xsl:template match="WHEEL">
<xsl:choose>
<xsl:when test="REFLECTORS">
<xsl:apply-templates select="REFLECTORS"/>
</xsl:when>
<xsl:otherwise>
<BICYCLE>
<COLOR><xsl:value-of select="../../COLOR"/></COLOR>
<WHEEL_TYPE><xsl:value-of select="WHEEL_TYPE"/></WHEEL_TYPE>
<FLAT><xsl:value-of select="FLAT"/></FLAT>
<REFLECTOR_NUM/>
<SHAPE/>
</BICYCLE>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="REFLECTORS">
<xsl:apply-templates select="REFLECTOR"/>
</xsl:template>
<xsl:template match="REFLECTOR">
<BICYCLE>
<COLOR><xsl:value-of select="../../../../COLOR"/></COLOR>
<WHEEL_TYPE><xsl:value-of select="../../WHEEL_TYPE"/></WHEEL_TYPE>
<FLAT><xsl:value-of select="../../FLAT"/></FLAT>
<REFLECTOR_NUM><xsl:value-of select="REFLECTOR_NUM"/></REFLECTOR_NUM>
<SHAPE><xsl:value-of select="SHAPE"/></SHAPE>
</BICYCLE>
</xsl:template>
</xsl:stylesheet>
Вывод:
<BICYCLES xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<BICYCLE>
<COLOR>BLUE</COLOR>
<WHEEL_TYPE>FRONT</WHEEL_TYPE>
<FLAT>NO</FLAT>
<REFLECTOR_NUM>1</REFLECTOR_NUM>
<SHAPE>SQUARE</SHAPE>
</BICYCLE>
<BICYCLE>
<COLOR>BLUE</COLOR>
<WHEEL_TYPE>FRONT</WHEEL_TYPE>
<FLAT>NO</FLAT>
<REFLECTOR_NUM>2</REFLECTOR_NUM>
<SHAPE>ROUND</SHAPE>
</BICYCLE>
<BICYCLE>
<COLOR>BLUE</COLOR>
<WHEEL_TYPE>REAR</WHEEL_TYPE>
<FLAT>NO</FLAT>
<REFLECTOR_NUM/>
<SHAPE/>
</BICYCLE>
</BICYCLES>
Что мне не нравится в этом, так это то, что я выводю атрибут цвета в несколькихформы:
<COLOR><xsl:value-of select="../../../../COLOR"/></COLOR>
<COLOR><xsl:value-of select="../../COLOR"/></COLOR>
<COLOR><xsl:value-of select="COLOR"/></COLOR>
<COLOR/>
Кажется, должен быть способ создать именованный шаблон и вызывать его из различных мест, где он необходим, и передавать какой-либо параметр, представляющий путь, обратно к <BICYCLE>
узел, к которому он относится.
Есть ли способ убрать это, скажем, с помощью именованного шаблона для велосипедных полей, для колесных полей и для отражательных полей?основано на том, что у «велосипеда» гораздо больше атрибутов, чем просто цвет, и я хочу, чтобы этот XSL легко изменялся для включения или исключения полей без необходимости изменять XSL в нескольких местах.