如何在XSLT中进行复杂的条件处理

时间:2019-06-20 12:24:52

标签: xml xslt

我正在尝试对Doxygen XML输出进行一些后处理,但无法实现我所需要的。

我正在修改一些现有的XSLT,并且对XML / XSL没有太多的经验,所以请原谅我说C而不是XML :)

input.xml

入口处理

<compounddef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="about" kind="page">
    <title>About This Document</title>
</compounddef> 

<compounddef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="ih" kind="page">
   <title>Ingress Handling</title>
</compounddef> 

expected_output.xml

  <compounddef id="about" kind="page">
    <title>About This Document</title>
  </compounddef>

  <sect1 id="ih">
    <title>About This Document</title>
  </sect1>

因此,基本上,如果碰巧是内页,则需要更改页面的缩进级别。即所有页面都需要成为sect1所有sect1-> sect2等... 当前,我正在尝试获得第一级,希望以后可以推断出该值(我认为,如果达到第一级,我可以调用带有其余处理参数的apply-templates)。

我确实知道如何匹配所有页面:

transform.xslt

<xsl:template match="doxygen/compounddef[@kind='page']">
   <compounddef id="{@id}" kind="{@kind}">
         <title><xsl:value-of select="title"/></title>
    </compounddef>
</xsl:template>

但是我需要添加一些if语句,以将当前元素与一组其他元素进行比较。在这里说C:

我需要创建一个所有内部页面的列表,并将上面模板中的每个元素与此列表进行比较,如果匹配,则输出sect1,如果不是compounddef

在C语言中听起来很简单,但是我不知道如何使用XSLT实现这一点。  最好使用XSLT 1.0解决方案,默认情况下我正在使用xsltpoc,但也可以考虑其他选项。

预先感谢您的任何想法。

Ilya。

更新

谢谢,这很有效。也可以使用XSLT 1.0。但仍然需要一些帮助:

input.xml

<compounddef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="about" kind="page">
    <title>About This Document</title>
    <innerpage refid="ih">Ingress Handling</innerpage>
</compounddef> 

<compounddef xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="ih" kind="page">
   <title>Ingress Handling</title>
</compounddef> 

transform.xslt

    <xsl:key name="inner-page-ref" match="compounddef[@kind='page']/innerpage" use="@refid"/>

    <!-- remove unmatched -->
    <xsl:template match="text()"/>

   <xsl:template match="/doxygen">
        <doxygen version="{@version}">
            <xsl:apply-templates select = "compounddef[@kind='page' and not(key('inner-page-ref', @id))]"/> 
        </doxygen>
    </xsl:template>


    <xsl:template match="doxygen/compounddef/innerpage" mode="list"> 
        <innerpage> 
            <xsl:value-of select="text()"/>
        </innerpage>

    </xsl:template>

    <xsl:template match="doxygen/compounddef/innerpage" mode="body"> 
        <xsl:copy>
            <xsl:apply-templates select = "/doxygen/compounddef[@kind='page' and key('inner-page-ref', @id)]"/> 
        </xsl:copy>
    </xsl:template>

    <xsl:template match="doxygen/compounddef[@kind='page'and not(key('inner-page-ref', @id))]"> 
            <compounddef id="{@id}" kind="{@kind}">
                <title><xsl:value-of select="title"/></title>
                <xsl:apply-templates mode="list" select = "innerpage"/>
                <xsl:apply-templates mode="body" select = "innerpage"/>
           </compounddef>
    </xsl:template>

    <xsl:template match="doxygen/compounddef[@kind='page'and (key('inner-page-ref', @id))]"> 

            <xsl:message> innerpage <xsl:value-of select ="@refid"/> </xsl:message>
            <sect1 id="{@id}" kind="{@kind}">
                <title><xsl:value-of select="title"/></title>
            </sect1>
    </xsl:template>

output.xml

 <compounddef id="packet_process" kind="page">
    <title>Packet Processing</title>
    <innerpage>Ingress Handling</innerpage>
    <innerpage>Packet Modification</innerpage>
    <innerpage>Packet Forwarding</innerpage>
    <innerpage>Egress Handling</innerpage>
    <innerpage>
      <sect1 id="ingress_handling" kind="page">
        <title>Ingress Handling</title>
      </sect1>
      <sect1 id="pm" kind="page">
        <title>Packet Modification</title>
      </sect1>
      <sect1 id="packet_forward" kind="page">
        <title>Packet Forwarding</title>
      </sect1>
      <sect1 id="packet_egress" kind="page">
        <title>Egress Handling</title>
      </sect1>
    </innerpage>
    <innerpage>
      <sect1 id="ingress_handling" kind="page">
        <title>Ingress Handling</title>
      </sect1>
      <sect1 id="pm" kind="page">
        <title>Packet Modification</title>
      </sect1>
      <sect1 id="packet_forward" kind="page">
        <title>Packet Forwarding</title>
      </sect1>
      <sect1 id="packet_egress" kind="page">
        <title>Egress Handling</title>
      </sect1>
    </innerpage>
    <innerpage>
      <sect1 id="ingress_handling" kind="page">
        <title>Ingress Handling</title>
      </sect1>
      <sect1 id="pm" kind="page">
        <title>Packet Modification</title>
      </sect1>
      <sect1 id="packet_forward" kind="page">
        <title>Packet Forwarding</title>
      </sect1>
      <sect1 id="packet_egress" kind="page">
        <title>Egress Handling</title>
      </sect1>
    </innerpage>
    <innerpage>
      <sect1 id="ingress_handling" kind="page">
        <title>Ingress Handling</title>
      </sect1>
      <sect1 id="pm" kind="page">
        <title>Packet Modification</title>
      </sect1>
      <sect1 id="packet_forward" kind="page">
        <title>Packet Forwarding</title>
      </sect1>
      <sect1 id="packet_egress" kind="page">
        <title>Egress Handling</title>
      </sect1>
    </innerpage>
  </compounddef>

这几乎很好,即我生成了几乎正确的输出。它适用于单个实例,但是如果我在不同页面中有很多内部页面,则无法使用。

即我需要为具有它的每个页面创建内部页面组,并对其进行处理。

寻找解决方案将在找到后更新。

1 个答案:

答案 0 :(得分:2)

声明密钥(作为xsl:transformxsl:stylesheet的顶级子代):

<xsl:key name="inner-page-ref" match="innerpage" use="@refid"/>

然后写一个模板

<xsl:template match="doxygen/compounddef[@kind='page' and key('inner-page-ref', @id)]">
   <sect1 id="{@id}">
         <title><xsl:value-of select="title"/></title>
    </sect1>
</xsl:template>

我希望XSLT 1中的方法可行,但对匹配模式中的键有一些限制。