简体   繁体   English

使用XSLT基于属性合并Xml元素

[英]Merge Xml elements based on attribute using XSLT

I want to merge the position elements and create a new element called travel after comparing the type attribute. 我想合并position元素,并在比较type属性后创建一个名为travel的新元素。 First type="from" has to merge with first type="to" found and should continue with the rest. 第一个type =“ from”必须与找到的第一个type =“ to”合并,其余应继续。

INPUT INPUT

<?xml version="1.0" encoding="UTF-8"?>
<JOB age="0" priority="N">
    <container ID="TSTU2345678" TP="4200"/>
    <container ID="TSTU3456789" TP="4200"/>
    <position refID="Y.Test:AA.01.01.1" name="AA0101.1" type="from"/>
    <position refID="Y.Test:AA.01.02.1" name="AA0102.1" type="from"/>
    <position refID="Y.Test:AA.02.02.1" name="AA0202.1" type="to"/>
    <position refID="Y.Test:AA.02.03.1" name="AA0203.1" type="to"/>
</JOB>

Required OUTPUT 所需的输出

<JOB age="0" priority="N">
    <Travel FromrefID="Y.Test:AA.01.01.1" Fromname="AA0101.1" TorefID="Y.Test:AA.02.02.1" Toname="AA0202.1"/>
    <Travel FromrefID="Y.Test:AA.01.02.1" Fromname="AA0102.1" TorefID="Y.Test:AA.02.03.1" Toname="AA0203.1"/>
</JOB>

What I have tried so far. 到目前为止我尝试过的。 It adds all To types into from element. 它将所有To类型添加到from元素中。 I am not sure how to select the first and mark it as used. 我不确定如何选择第一个并将其标记为已使用。 Also how do I change the attribute names. 另外,如何更改属性名称。 Please help. 请帮忙。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="position" match="job/position" use="@type" />
    <xsl:template match="job">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/">
        <JOB>
            <xsl:apply-templates select="job/@*" />
            <xsl:for-each select="key('position','from')">
                <Travel>
                    <xsl:apply-templates select="@*" />

                    <xsl:for-each select="key('position','to')">
                        <To>
                            <xsl:apply-templates select="@*" />
                        </To>
                    </xsl:for-each>
                </Travel>

            </xsl:for-each>
        </JOB>
    </xsl:template>

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

</xsl:stylesheet>

Thanks. 谢谢。

I'd suggest you look at it this way: 我建议你这样看:

XSLT 1.0 XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="to" match="position[@type='to']" use="count(preceding-sibling::position[@type='to'])" />

<xsl:template match="/JOB">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:for-each select="position[@type='from']">
            <xsl:variable name="to" select="key('to', position() - 1)" />
            <Travel FromrefID="{@refID}" Fromname="{@name}" TorefID="{$to/@refID}" Toname="{$to/@name}"/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Note that we are assuming here that there are equal number of "from" and "to" positions (or at lest that the number of "from" positions is not less than the number of "to" positions). 注意,这里我们假设“ from”和“ to”位置的数目相等(或者至少“ from”位置的数目不少于“ to”位置的数目)。

An alternative XSLT 1.0 solution 替代XSLT 1.0解决方案

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|position[@type='from']"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="position[@type='from']">
        <xsl:variable name="fromPos" select="position()"/>
        <Travel FromRefId="{@refID}" Fromname="{@name}">
            <xsl:apply-templates select="position[@type='to'][position()=$fromPos]"/>
        </Travel>
    </xsl:template>

    <xsl:template match="position[@type='to']">
        <xsl:attribute name="TorefID">
            <xsl:value-of select="@refID"/>
        </xsl:attribute>
        <xsl:attribute name="Toname">
            <xsl:value-of select="@name"/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM