XSLT:使子节点成为上下文节点的兄弟节点

时间:2011-02-28 21:32:01

标签: xml xslt

搜索了这个并没有找到答案,所以这里......

我有一些类似于以下内容的xml:

<?xml version="1.0" encoding="utf-8"?>
<footnote ref="1">
    <para>Here is some text about some guy who made
        <emphasis role="italic">fascinating</emphasis> comment I want to quote
        <blockquote> So I went to this place and met this guy....</blockquote>
        It seemed more interesting at the time.
    </para>
</footnote>

我想使用xslt将其更改为新架构(使用新的命名空间前缀)

<?xml version="1.0" encoding="utf-8"?>
<nns:footnote ref="1">
    <nns:fn-para>Here is some text about some guy who made
        <nns:emph type="it">fascinating</nns:emph> comment I want to quote:
    </nns:fn-para>
    <nns:fn-blockquote>
        <nns:bq-para>So I went to this place and met this guy....</nns:bq-para>
    </nns:fn-blockquote>
    <nns:fn-para> It seemed more interesting at the time.</nns:fn-para>
</nns:footnote>

我尝试过一些事情......采取一个脚注,它是脚注的后代并循环遍历孩子,但这是有问题的,因为它不仅是para中的文本节点,还有emph标签,而我仍然不知道如何将一个子节点放在树上并在结果树中放置... doe有意义吗?

1 个答案:

答案 0 :(得分:3)

编辑:小型重构和扩展说明。

此样式表:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:nns="nns">
    <xsl:key name="kNodeByPrecedingBlock"
             match="para/node()[not(self::blockquote)]"
             use="generate-id(
                     (..|preceding-sibling::*[self::blockquote][1])[last()]
                  )"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="footnote">
        <nns:footnote>
            <xsl:apply-templates select="node()|@*"/>
        </nns:footnote>
    </xsl:template>
    <xsl:template match="para">
        <xsl:apply-templates select=".|blockquote" mode="group"/>
    </xsl:template>
    <xsl:template match="emphasis">
        <nns:emph>
            <xsl:apply-templates select="node()|@*"/>
        </nns:emph>
    </xsl:template>
    <xsl:template match="emphasis/@role">
        <xsl:attribute name="type">
            <xsl:value-of select="substring(.,1,2)"/>
        </xsl:attribute>
    </xsl:template>
    <xsl:template match="blockquote">
        <nns:fn-blockquote>
            <nns:bq-para>
                <xsl:apply-templates/>
            </nns:bq-para>
        </nns:fn-blockquote>
    </xsl:template>
    <xsl:template match="para" mode="group" name="makePara">
        <xsl:variable name="vGroup"
             select="key('kNodeByPrecedingBlock',generate-id())"/>
        <xsl:if test="$vGroup">
            <nns:fn-para>
                <xsl:apply-templates select="$vGroup"/>
            </nns:fn-para>
        </xsl:if>
    </xsl:template>
    <xsl:template match="*" mode="group">
        <xsl:apply-templates select="."/>
        <xsl:call-template name="makePara"/>
    </xsl:template>
</xsl:stylesheet>

输出:

<nns:footnote ref="1" xmlns:nns="nns">
   <nns:fn-para>Here is some text about some guy who made 
      <nns:emph type="it">fascinating</nns:emph> comment I want to quote 
   </nns:fn-para>
   <nns:fn-blockquote>
      <nns:bq-para> So I went to this place and met this guy....</nns:bq-para>
   </nns:fn-blockquote>
   <nns:fn-para>         It seemed more interesting at the time. 
   </nns:fn-para>
</nns:footnote>

注意:覆盖的身份规则(仅适用于样式,但它是一个很好的模式)。四个直接转换规则与footnoteemphasis的{​​{1}},@roleemphasis属性相匹配。对匹配“内联”blockquote的子项进行分组:第一个前面的“块”元素或para父元素的生成ID。 para将模板应用于自身的分组规则以及para模式中的“阻止”元素。 "group"模式中的规则匹配para(也称为"group"):如果存在具有上下文节点的组生成ID作为键值,则输出段落。规则匹配makePara模式中的任何元素(它将是任何“块”元素):将模板应用于自身(“重置”模式)并调用"group"命名模板。