xslt选择跟随特定<parenttag>元素</parenttag> </tag>的所有<tag>元素

时间:2013-12-08 16:41:19

标签: xml xslt

考虑我有这个XML文件:

<p>my name is :
  <bold>reza</bold>
  <bold>saket</bold>
  <bold>ali</bold>
  <bold>abadi</bold>
</p>
<p>my name is :
  <bold>
    <italic>mehran</italic>
  </bold>
  <bold>
    <italic>bazargan</italic>
  </bold>
  <bold>
    <italic>dashtestani</italic>
  </bold>
</p>

现在我希望输出结果为:

<p> my name is :
  <bold>reza saket ali abadi</bold>
</p>
<p>
  <bold>
    <italic>mehran bazargan dashtestani</italic>
  </bold>
</p>

1 个答案:

答案 0 :(得分:0)

我会编写一个身份转换,然后通过添加这样的模板(未测试)来修改它。首先,对粗体和斜体元素进行特殊处理:

<xsl:template match='bold | italic'>
  <xsl:variable name="name" select="name()"/>
  <xsl:choose>
    <!--* if our preceding sibling has the same element
        * type, then we have already been processed; 
        * do nothing. *-->
    <xsl:when test="preceding-sibling::*[1][name() = $name]"/>

    <!--* if our next following sibling has the same element
        * type, then incorporate it. *-->
    <xsl:when test="following-sibling::*[1][name() = $name]">
      <xsl:copy>
        <xsl:apply-templates/>
        <xsl:apply-templates select="following-sibling::node()[1]" 
                             mode="incorporation"/>
      </xsl:copy>
    </xsl:when>

    <!--* otherwise, proceed normally *-->
    <xsl:otherwise>
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

然后,模板处理我们在整合模式中可能遇到的所有节点类型:

<xsl:template match='bold | italic' mode="incorporation">
  <xsl:variable name="name" select="name()"/>

  <xsl:apply-templates select="node()"/>
  <!--* if our next following sibling has the same element
      * type, then incorporate it. *-->
  <xsl:if test="following-sibling::*[1][name() = $name]">
    <xsl:apply-templates select="following-sibling::node()[1]" 
                         mode="incorporation"/>
  </xsl:if>     
</xsl:template>

<xsl:template match='comment()' 
              mode='incorporation'>
 <xsl:comment>
  <xsl:value-of select="."/>
 </xsl:comment>
 <xsl:apply-templates select="following-sibling::node()[1]" 
                      mode="incorporation"/>
</xsl:template>

<xsl:template match='processing-instruction()' 
              mode='incorporation'>
 <xsl:variable name="pitarget" select="name()"/>
 <xsl:processing-instruction name="{$pitarget}">
  <xsl:value-of select="."/>
 </xsl:processing-instruction>
 <xsl:apply-templates select="following-sibling::node()[1]" 
                      mode="incorporation"/>
</xsl:template>

<!--* this one accidentally omitted in first version *-->
<xsl:template match='text()' mode='incorporation'>
  <xsl:value-of select="."/>
  <xsl:apply-templates select="following-sibling::node()[1]" 
                       mode="incorporation"/>
</xsl:template>

最后,模板用于抑制我们在组合模式中遇到的节点,以防止重复:

<xsl:template match='node()[not(self::*) 
                     and preceding-sibling::*[1]
                     [self::bold or self::italic]]'/>

这只处理一个粗体或斜体;因为你想要嵌套它们,就像在你的第二个例子中那样,你需要运行它两次 - 或重复运行它,直到它的输出与它的输入相同,如果你可能有大于两个深的嵌套粗体和斜体元素。 / p>