XSLT:选择键()或另一个键()

问题描述 投票:0回答:1

我有元素连接器,它有源和目标。但是源有时可能是一个元素,有时是另一个元素(初始节点或活动)。所以我有两把钥匙。我想用一把钥匙或另一把钥匙。我的XML输入示例:

            <packagedElement>
                <node xmi:type="uml:InitialNode" xmi:id="EAID_a" name="ActivityInitial">
                    <outgoing xmi:idref="EAID_A7A0C176_5CCC_4bf2_AED2_AEB05FB741AF"/>
                </node>
                <group xmi:type="uml:ActivityPartition" xmi:id="EAID_b" name="Partition_1">
                    <node xmi:idref="EAID_c"/>
                </group>
                <packagedElement xmi:type="uml:Activity" xmi:id="EAID_c" name="Activity1"/>
                <group xmi:type="uml:ActivityPartition" xmi:id="EAID_d" name="Partition_2">
                    <node xmi:idref="EAID_e"/>
                </group>
                <packagedElement xmi:type="uml:Activity" xmi:id="EAID_e" name="Activity2"/>
            </packagedElement>
            ...
            <connector xmi:idref="EAID_A7A0C176_f">
                <source xmi:idref="EAID_a"/>        
                <target xmi:idref="EAID_c"/>
            </connector>
            <connector xmi:idref="EAID_CEB43B7F_g"/>
                <source xmi:idref="EAID_c"/>
                <target xmi:idref="EAID_e"/>
            </connector>

这是我的XSLT:


    <xsl:key name="grp" match="group" use="node/@xmi:idref" />
    <xsl:key name="ini" match="*[@xmi:type='uml:InitialNode']" use="@xmi:id" />

    ...

    <connector xmi:idref="EAID_CONNECTR{substring(@xmi:id, 14, 28)}">
         <source xmi:idref="(EAID_LIFELINE{key('grp', @source)/substring(@xmi:id, 14, 28)})({key('ini', @source)/@xmi:id})"/>
         <target xmi:idref="EAID_LIFELINE{key('grp', @target)/substring(@xmi:id, 14, 28)}"/>
    </connector>

对于两个连接器,WRONG xml输出看起来像这样:

 <connector xmi:idref="EAID_CONNECTR_f">
        <source xmi:idref="(EAID_LIFELINE)(EAID_a)"/>
        <target xmi:idref="EAID_LIFELINE_c"/>
 </connector>
 <connector xmi:idref="EAID_CONNECTR_g">
        <source xmi:idref="(EAID_LIFELINE_c)()"/>
        <target xmi:idref="EAID_LIFELINE_e"/>
 </connector>

但XML输出应该如下所示:

 <connector xmi:idref="EAID_CONNECTR_5CCC_4bf2_AED2_AEB05FB741AF">
        <source xmi:idref="EAID_a"/>
        <target xmi:idref="EAID_LIFELINE_c"/>
 </connector>
 <connector xmi:idref="EAID_CONNECTR_ED15_4f03_8D9B_8EF054BD458D">
        <source xmi:idref="EAID_LIFELINE_c"/>
        <target xmi:idref="EAID_LIFELINE_e"/>
 </connector>

因此,如果我使用密钥“grp”,则应该有前缀EAID_LIFELINE,但如果我使用密钥“ini”,则应该具有所有不带前缀的id。如何根据我的需要编辑XSLT?

xml xslt xpath xslt-2.0 xmi
1个回答
0
投票

我可以理解当前的XSLT如何与您的XML和期望的输出相对应,部分原因是您的XSLT正在寻找@source属性,这在XML中不存在。

但总的来说,如果您确实使用的是XSLT 2.0,那么这可能是if ... else ...构造的一种情况,因此您可以像这样编写表达式:

  <source xmi:idref="{
        if (key('grp', @source)) 
        then concat('EAID_LIFELINE', key('grp', @source)/substring(@xmi:id, 14, 28)) 
        else key('ini', @source)/@xmi:id
    }"/>

还要注意,使用“ini”键令人困惑......

key('ini', @source)/@xmi:id

因为“ini”键具有@xmi:id的“use”属性,所以如果@source等于@xmi:id元素上的node,则键只会返回任何内容。换句话说,key('ini', @source)/@xmi:id等于@source

© www.soinside.com 2019 - 2024. All rights reserved.