在XSLT中,如何一次访问两个兄弟节点的属性值(访问节点a时,我需要访问节点b)?

时间:2011-11-29 19:46:37

标签: xml xslt

如何一次打印所有消息和生命线节点的属性值?
通过“立刻”,我的意思是在打印出消息名称时,我需要访问生命线节点。我唯一关注的属性是:生命线/ @名称和消息/ @名称。我正在尝试使用消息移动的生命线名称打印出消息名称。您不必发布答案来解决我将如何将消息与其开始和结束生命线相关联的问题。这很棘手。我只需要知道如何一次访问生命线和消息属性值。或者如果它甚至可能。 XSLT显示输出格式。

对于以下XML,只关注生命线,消息和packagedElement节点。对于上下文,XML是具有序列图的UML模型。不需要保留序列消息的顺序。我正在客户端开发,因此样式表href行包含在XML中。我无法在样式表href之外更改XML。包含所有必需的命名空间。我正在将XML转换为文本。我想将这些值打印为制表符分隔文本。

XML:

 <?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet href="multiple nonthreaded iers.xsl" type="text/xsl"?>
 <uml:Model xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"  xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/3.0.0/UML" xmi:id="idModel" name="main">
  <packagedElement xmi:type="uml:Package" xmi:id="idPackage" name="ThreadedIERPackage">
    <packagedElement xmi:type="uml:Collaboration" xmi:id="idCollaboration" name="ThreadedIERCollaboration">
      <ownedBehavior xmi:type="uml:Interaction" xmi:id="idInteraction">
        <lifeline xmi:type="uml:Lifeline" xmi:id="_OccJQguaEeGMo_zLRqy_vg" name="Lifeline1"/>
        <lifeline xmi:type="uml:Lifeline" xmi:id="_Oo87QguaEeGMo_zLRqy_vg" name="Lifeline2" coveredBy="_QrWQ2AuaEeGMo_zLRqy_vg _R4-hlQuaEeGMo_zLRqy_vg _QrWQ0guaEeGMo_zLRqy_vg"/><!-- can ignore the last id -->
        <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_R4-hlQuaEeGMo_zLRqy_vg" name="MessageOccurrenceSpecification2" covered="_Oo87QguaEeGMo_zLRqy_vg" event="_R4-hlguaEeGMo_zLRqy_vg" message="_R4-hlwuaEeGMo_zLRqy_vg"/>
        <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_QrWQ2AuaEeGMo_zLRqy_vg" name="MessageOccurrenceSpecification1" covered="_Oo87QguaEeGMo_zLRqy_vg" event="_QrWQ2QuaEeGMo_zLRqy_vg" message="_QrWQ2guaEeGMo_zLRqy_vg"/>
        <fragment xmi:type="uml:BehaviorExecutionSpecification" xmi:id="_QrWQ0guaEeGMo_zLRqy_vg" name="BehaviorExecutionSpecification1" covered="_Oo87QguaEeGMo_zLRqy_vg" start="_QrWQ2AuaEeGMo_zLRqy_vg" finish="_R4-hlQuaEeGMo_zLRqy_vg"/>
        <message xmi:type="uml:Message" xmi:id="_QrWQ2guaEeGMo_zLRqy_vg" name="Message1" receiveEvent="_QrWQ2AuaEeGMo_zLRqy_vg"/>
        <message xmi:type="uml:Message" xmi:id="_R4-hlwuaEeGMo_zLRqy_vg" name="Message2" messageSort="reply" sendEvent="_R4-hlQuaEeGMo_zLRqy_vg"/>
      </ownedBehavior>
    </packagedElement>
    <packagedElement xmi:type="uml:CallEvent" xmi:id="_QrWQ2QuaEeGMo_zLRqy_vg" name="CallEvent1"/>
    <packagedElement xmi:type="uml:CallEvent" xmi:id="_R4-hlguaEeGMo_zLRqy_vg" name="CallEvent2"/>
  </packagedElement>
  <profileApplication xmi:type="uml:ProfileApplication" xmi:id="idProfileApplication">
    <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="idProfileAnnotation" source="http://www.eclipse.org/uml2/2.0.0/UML">
      <references xmi:type="ecore:EPackage" href="pathmap://SysMLActivityExtensionsProfile.uml#ProfileContentId"/>
    </eAnnotations>
    <appliedProfile xmi:type="uml:Profile" href="pathmap://SysMLActivityExtensionsProfile.uml#ActivityProfileId"/>
  </profileApplication>
</uml:Model>

XSLT:                         

<xsl:template match="/">
<xsl:text>#Sending Lifeline (Producer)</xsl:text>
<xsl:value-of select="$tab"/>

<xsl:text>Receiving Lifeline (Consumers)</xsl:text>
<xsl:value-of select="$tab"/>

<xsl:text>Name(s)</xsl:text>
<xsl:value-of select="$tab"/>
<xsl:text>ID</xsl:text>
    <xsl:value-of select="$tab"/>
<xsl:value-of select="$newline"/>
<xsl:apply-templates />

</xsl:template>


<xsl:template match="packagedElement/ownedBehavior"> 
<xsl:for-each select="lifeline"><!-- prints all lifelines-->
    <xsl:value-of select="@name"/><xsl:text>.OE</xsl:text>
    <xsl:value-of select="$tab"/>
</xsl:for-each>

    <xsl:text>OE --> OE</xsl:text>
    <xsl:value-of select="$tab"/>

    <xsl:value-of select="message/@name"/>
    <xsl:value-of select="$tab"/>
</xsl:template>

</xsl:stylesheet>

我尝试过: 我创建了一个packagedElement / ownedBehavior模板来访问两个节点(生命线,消息),因为它们都是孩子。但是,除非我使用for -each,否则它不会打印出所有消息或生命线。但是,如果我使用for-each,那么我只能访问消息或生命线,而不是两者。

我尝试过使用多个模板,一个用于生命线,另一个用于消息。示例:<xsl:template match="lifeline">。当然,我无法一次访问两个节点的属性。甚至,如果我使用呼叫模板功能。我试过了,但失败了。

这是一个棘手的问题,所以我感谢您的回复。

2 个答案:

答案 0 :(得分:2)

通常,使用union运算符 - | - 在一个模板中选择两种类型的元素:

<xsl:template match="lifeline|message">

或者:

<xsl:template match="packagedElement/ownedBehavior"> 
    <xsl:for-each select="lifeline|message">
        <!-- code here -->
    </xsl:for-each>
</xsl:template>

或者,迭代一个或另一个,随时关联。例如:

<xsl:template match="packagedElement/ownedBehavior"> 
    <xsl:for-each select="lifeline">
        <xsl:value-of select="../message[<some_condition_here>]"/>
        <!-- code here -->
    </xsl:for-each>
</xsl:template>

...其中<some_condition_here>是选择关联节点的谓词。

答案 1 :(得分:2)

for-each lifeline元素../message上,您可以对同一ownedBehavior的所有邮件使用{{1}}。不确定你应该选择哪一个,可能是相同的位置?