比较两个值与可访问的祖先

时间:2018-09-21 11:40:52

标签: xml xslt xpath

我必须在XML中查找相同引用的值,并且通过此比较,我必须查找并获取祖先的数据。 XML看起来像这样:

<Section version="1" subversion="1" key="xy://data/Section/42df2def-b485-4600-9701-a9a0cb3fb0ba/?language=de-DE">
    <Heading>This is a heading</Heading>
    <Sequence version="1" subversion="1" key="xy://data/Sequence/70533309-defa-46af-a419-56e134ed0757/"> 
        <Target>How to do ABC</Target>
        <Step StepId="id12345">
            <Condition>
                <Para>First step.</Para>
                <Para>Do ... to get ...</Para>
            </Condition>
        </Step>
        <Step>
            <Condition>
                <Para>Second step.</Para>
                <Para>Reference: <StepRef StepIdRef="id12345"/></Para>
            </Condition>
        </Step>
    </Sequence>
</Section>

<Section version="1" subversion="1" key="xy://data/c2e4fa40-372e-4fe7-a63d-a73848c8f28b/?language=de-DE">
    <Heading>This is another heading</Heading>
    <Sequence version="1" subversion="1" key="27329b6b-95ef-4959-af95-f04f99391005/">
        <Target>How to do XYZ</Target>
        <Step>
            <Condition>
                <Para>Important step, see <StepRef StepIdRef="id12345"/></Para>
            </Condition>
        </Step>
    </Sequence>
</Section>

我想要的内容应如下所示:

<a href="" my.id="{key from Sequence}" my.version="{version from Sequence}" my.type="{name of object type}" fragment="{stepId_version_type}"/>

转移到我的情况下,两个示例都应如下所示:

<p>Reference: <a href="" my.id="70533309-defa-46af-a419-56e134ed0757" my.version="1" my.type="Sequence" fragment="id12345_1_Sequence"/>
<p>Important step, see <a href="" my.id="70533309-defa-46af-a419-56e134ed0757" my.version="1" my.type="Sequence" fragment="id12345_1_Sequence"/>

到目前为止,我的XSLT看起来像这样:

<xsl:template match="StepRef">
    <xsl:param name="catchStep" select="StepIdRef">
        <xsl:if test="$catchStep=//@StepId">
            <a>
                <xsl:attribute name="href"/>

                <!-- To get the stepId -->
                <xsl:attribute name="my.id"><xsl:value-of select="ancestor::*[@key]/substring-before(substring-after(substring-after(@key, 'data/'), '/'), '/')"/></xsl:attribtue>
                <!-- To get the version -->
                <xsl:attribute name="my.version"><xsl:value-of select="ancestor::*[@key]/@version"/></xsl:attribtue>
                <!-- To get the object type -->
                <xsl:attribute name="my.type"><xsl:value-of select="ancestor-or-self::*[@key]/substring-before(substring-after(@key, 'data/'), '/')"/></xsl:attribtue>

                <xsl:attribute name="fragment">
                    <!-- To get the stepId -->
                    <xsl:value-of select="$firstStep"/>
                    <xsl:text>_</xsl:text>
                    <!-- To get the version -->
                    <xsl:value-of select="ancestor::*[@key]/@version"/>
                    <xsl:text>_</xsl:text>
                    <!-- To get the object type -->
                    <xsl:value-of select="ancestor::*[key]/substring-before(substring-after(@key, 'data/'), '/')"/>
                </xsl:attribute>
            </a>
        </xsl:if>
</xsl:template>

主要问题:

  • 我总是以某种方式捕获Section而不是Sequence(并且我接收到相应的数据)
  • 似乎只适用于同一主题中的步骤
  • 我不知道如何访问相同的变量并从中创建XPath控件
  • 我认为我的XSLT编码不正确

1 个答案:

答案 0 :(得分:3)

您似乎可以在此处使用xsl:key来查找步骤

因此,如果您使用的模板与StepRef相匹配,则可以执行key('Steps', @StepIdRef)来查找引用的步骤(要获取父项,请执行key('Steps', @StepIdRef)..)。

您可以使用Attribute Value Templates进一步简化代码,使创建属性更加容易。

尝试使用此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes" />

  <xsl:key name="Steps" match="Step" use="@StepId" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="StepRef">
    <xsl:variable name="object" select="key('Steps', @StepIdRef)/.." />
    <a href="" 
        my.id="{substring-before(substring-after(substring-after($object/@key, 'data/'), '/'), '/')}" 
        my.version="{$object/@version}" 
        my.type="{local-name($object)}"
        fragment="{@StepIdRef}_{$object/@version}_{local-name($object)}"/>
  </xsl:template>
</xsl:stylesheet>