Конкатенация узлов XML с использованием XSLT - PullRequest
0 голосов
/ 05 февраля 2019

Мое требование - преобразовать следующий исходный XML в целевой XML.Не могли бы вы помочь мне с требуемым XSLT?

Исходный XML:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
    <property><namevalue name="loccode1">BIN01</namevalue></property>
    <property><namevalue name="locdesc1">Description for BIN01</namevalue></property>
    <property><namevalue name="loccode2">BIN02</namevalue></property>
    <property><namevalue name="locdesc2">Description for BIN02</namevalue></property>
    <property><namevalue name="loccode3">BIN03</namevalue></property>
    <property><namevalue name="locdesc3">Description for BIN03</namevalue></property>
</catalog>

Целевой XML:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
    <property>
        <namevalue name="location1">BIN01#Description for BIN01</namevalue>
    </property>
    <property>
        <namevalue name="location2">BIN02#Description for BIN02</namevalue>
    </property>
    <property>
        <namevalue name="location3">BIN03#Description for BIN03</namevalue>
    </property>
</catalog>

Требуется объединить значения namevalue узлы с атрибутами loccode<seq> и locdesc<seq>.Не могли бы вы помочь мне добиться этого?

Следующий фрагмент

<xsl:apply-templates select="catalog/property/namevalue[@name='loccode2'] |  catalog/property/namevalue[@name='locdesc2']" />

ожидает от меня явного указания имени атрибута, и вывод будет BIN01Description for BIN01 (я даже не могу добавитьразделитель).Есть ли способ динамической передачи атрибута (например, loccode<seq> или locdesc<seq>) и добавления разделителя между скопированным текстом.

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019
    <xsl:template match="catalog">
    <catalog>
        <xsl:apply-templates select="property"/>
    </catalog>
</xsl:template>
<xsl:template match="property/namevalue">
    <xsl:choose>
        <xsl:when test="contains(., 'Description for ')"/>
        <xsl:otherwise>
            <property>
                <namevalue>
                    <xsl:if test="@name">
                        <xsl:attribute name="name">
                            <xsl:value-of select="concat('location', substring-after(@name, 'loccode'))"/>
                        </xsl:attribute>
                        <xsl:value-of select="concat(.,'#','Description for ',.)"/>
                    </xsl:if>
                </namevalue>
            </property>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Пожалуйста, проверьте этот код.

0 голосов
/ 05 февраля 2019

Вы также можете использовать это как альтернативу:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs" version="1.0">

    <xsl:strip-space elements="*"/>

    <xsl:output indent="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="property[namevalue[contains(@name, 'loccode')]]">
        <property>
            <xsl:for-each select="namevalue[contains(@name, 'loccode')]">
                <xsl:variable name="seq" select="concat('locdesc', substring-after(@name, 'loccode'))"/>
                <xsl:copy>
                    <xsl:apply-templates select="@*"/>
                    <xsl:value-of select="concat(., '#', //namevalue[@name = $seq])"/>
                </xsl:copy>
            </xsl:for-each>
        </property>
    </xsl:template>

    <xsl:template match="property[namevalue[contains(@name, 'locdesc')]]"/>

</xsl:stylesheet>

см. Эту ссылку: http://xsltransform.net/3MP2uBK/1

0 голосов
/ 05 февраля 2019

Есть ли способ динамической передачи атрибута (например, loccode или locdesc)

Да.Вы можете использовать:

/catalog/property[starts-with(namevalue/@name, 'loccode')]

, чтобы выбрать только location codes свойства.


В качестве альтернативы, если структура следует регулярному шаблону, вы можете использовать:

/catalog/property[position() mod 2 = 1]

, чтобы сделать тот же выбор, а затем:

following-sibling::property[1]

выбрать соседнее свойство location description.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...