我需要使用XSLT映射此格式的值:
<Package>
<WorkflowProcesses>
<WorkflowProcess>
<Activities>
<Activity Name="First Activity" Id="123">
</Activity>
<Activity Name="Second Activity" Id="456">
</Activity>
<Activity Name="Third Activity" Id="789">
</Activity>
</Activities>
<Transitions>
<Transition To="789" From="456" Id="ABC">
</Transition>
<Transition To="456" From="123" Id="XYZ">
</Transition>
</Transitions>
</WorkflowProcess>
</WorkflowProcesses>
</Package>
采用以下格式:
<variable type="State">
<stateId type="Integer">123</stateId>
<stateName type="String">First Activity</stateName>
<previousStatesId type="String[]">
</previousStatesId>
<nextStatesId type="String[]">
<item>456</item>
</nextStatesId>
</variable>
<variable type="State">
<stateId type="Integer">456</stateId>
<stateName type="String">Second Activity</stateName>
<previousStatesId type="String[]">
<item>123</item>
</previousStatesId>
<nextStatesId type="String[]">
<item>789</item>
</nextStatesId>
</variable>
<variable type="State">
<stateId type="Integer">789</stateId>
<stateName type="String">Third Activity</stateName>
<previousStatesId type="String[]">
<item>456</item>
</previousStatesId>
<nextStatesId type="String[]">
</nextStatesId>
</variable>
我正在努力的部分是从“转换”部分获取值并将它们分配到正确的区域('nextStatesId'和'previousStatesId');其他一切都按预期工作。
到目前为止,我已成功使用以下方法映射活动项目:
<xsl:template match="Activities">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Activity [@Name]">
<variable type="State">
<stateId type="Integer"><xsl:value-of select="@Id"/></stateId>
<stateName type="String"><xsl:value-of select="@Name"/></stateName>
</variable>
</xsl:template>
</xsl:stylesheet>
我可以用它来识别所有的Transition项,然后我将比较Transition的id和当前的Activity,但它在上面的模板中不起作用。我假设这是因为模板没有整个XML文件的可见性,因此无法理解映射
<xsl:for-each select="Package/WorkflowProcesses/WorkflowProcess/Transitions/Transition">
<p>...do some stuff...</p>
</xsl:for-each>
通常,如果我正在编码,我只需将它们推入两个列表然后搜索它们。我打算在这里做的只是循环遍历每个Activity中的所有转换,并使用前一个/下一个状态id的简单'if'语句......但这似乎失败了。
有没有人知道另一种方法来实现这个目标?
答案 0 :(得分:1)
如果您将for-each
放在模板中,它将在活动中搜索孩子 Package/...
。但没有。
您在此处尝试执行的操作是访问根节点。因此,在/
之前加上斜杠“Package
”。
<xsl:for-each select="/Package/WorkflowProcesses/WorkflowProcess/Transitions/Transition">
<p>...do some stuff...</p>
</xsl:for-each>
但是,我不建议在这里使用for-each
。 applay-templates
会更合适。
尝试:
<xsl:template match="Activity[@Name]">
<variable type="State">
<stateId type="Integer">
<xsl:value-of select="@Id"/>
</stateId>
<stateName type="String">
<xsl:value-of select="@Name"/>
</stateName>
<previousStatesId type="String[]">
<xsl:apply-templates select="//Transition[@To =current()/@Id]"
mode="from" />
</previousStatesId>
<nextStatesId type="String[]">
<xsl:apply-templates select="//Transition[@From =current()/@Id]"
mode="to" />
</nextStatesId>
</variable>
</xsl:template>
<xsl:template match="Transition" mode="from">
<item>
<xsl:value-of select="@From"/>
</item>
</xsl:template>
<xsl:template match="Transition" mode="to">
<item>
<xsl:value-of select="@To"/>
</item>
</xsl:template>
答案 1 :(得分:1)
这种转变似乎符合你的要求。
你的“这种格式”格式不正确,因为它没有根元素,所以我添加了一个虚拟<root>
元素。
转换使用键来按属性访问Transition
元素。
我想知道你真的是否需要空格previousStatesId
和nextStatesId
输出元素中的空格和换行内容?此变换生成自闭合空元素。如果您需要严格的准确性,这种改变并不难。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="transition-from" match="Transition" use="@From"/>
<xsl:key name="transition-to" match="Transition" use="@To"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="Package/WorkflowProcesses/WorkflowProcess/Activities/Activity"/>
</root>
</xsl:template>
<xsl:template match="Activity">
<xsl:variable name="from-here" select="key('transition-from', @Id)"/>
<xsl:variable name="to-here" select="key('transition-to', @Id)"/>
<variable type="State">
<stateId type="Integer">
<xsl:value-of select="@Id"/>
</stateId>
<stateName type="String">
<xsl:value-of select="@Name"/>
</stateName>
<previousStatesId type="String[]">
<xsl:if test="$to-here">
<item>
<xsl:value-of select="$to-here/@From"/>
</item>
</xsl:if>
</previousStatesId>
<nextStatesId type="String[]">
<xsl:if test="$from-here">
<item>
<xsl:value-of select="$from-here/@To"/>
</item>
</xsl:if>
</nextStatesId>
</variable>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
<root>
<variable type="State">
<stateId type="Integer">123</stateId>
<stateName type="String">First Activity</stateName>
<previousStatesId type="String[]"/>
<nextStatesId type="String[]">
<item>456</item>
</nextStatesId>
</variable>
<variable type="State">
<stateId type="Integer">456</stateId>
<stateName type="String">Second Activity</stateName>
<previousStatesId type="String[]">
<item>123</item>
</previousStatesId>
<nextStatesId type="String[]">
<item>789</item>
</nextStatesId>
</variable>
<variable type="State">
<stateId type="Integer">789</stateId>
<stateName type="String">Third Activity</stateName>
<previousStatesId type="String[]">
<item>456</item>
</previousStatesId>
<nextStatesId type="String[]"/>
</variable>
</root>