XSLT: выберите ключ () ИЛИ другой ключ () - PullRequest
0 голосов
/ 17 апреля 2019

У меня есть соединитель элементов, который имеет источник и цель. Но источником может быть иногда один элемент, иногда другой (начальный узел или действие). Так что у меня есть 2 ключа для этого. Я хочу использовать либо один ключ, либо другой. Пример моего ввода 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>

Для двух разъемов неправильный вывод 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", у него должен быть весь идентификатор без префикса. Как отредактировать XSLT для того, что я хочу?

1 Ответ

0 голосов
/ 18 апреля 2019

Я мог бы понять, как ваш текущий 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" имеет атрибут "use", равный @xmi:id, он будет возвращать только что-либо, если @sourceравняется @xmi:id на элементе node.Другими словами key('ini', @source)/@xmi:id равно просто @source.

...