【问题标题】:XSLT: Select key() OR another key()XSLT:选择键()或另一个键()
【发布时间】:2019-04-17 09:44:18
【问题描述】:

我有元素连接器,它有源和目标。但源有时可能是一个元素,有时是另一个元素(初始节点或活动)。所以我有 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”,则所有 id 都应该没有前缀。 如何根据需要编辑 XSLT?

【问题讨论】:

  • 如果 (a) 您展示了输入样本,并且 (b) 您将无法读取的十六进制 idref 值替换为“X”、“Y”和“ Z' 使整个内容更具可读性。
  • 我添加了我的输入示例,将 idref 替换为 a,b,c,d,... 是否更具可读性?
  • 是的,它更具可读性,但恐怕我仍然不明白您要实现的目标。问题是,您已经显示了所需的输出,但我不知道将此输出与输入相关联的规则是什么。向我们展示完全不同的 XSLT 代码并没有真正的帮助。
  • 好的,很简单:如果有来自 key ini 的 id(这意味着源是初始节点)使用 id 和所有名称,如果你正在使用 key grp(这意味着源是活动节点 - group 有 id:ref) 添加前缀 LIFELINE 并使用 group id 中的子字符串。
  • 看看错误的xml输出和第二个输出的区别。首先有 (EAID_LIFELINE) 并且不应该有

标签: xml xslt xpath xslt-2.0 xmi


【解决方案1】:

我可以理解您当前的 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 等于node 元素上的@xmi:id 时,该键才会返回任何内容。换句话说,key('ini', @source)/@xmi:id 就等于 @source

【讨论】:

    猜你喜欢
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多