XSLT:全部复制,但'剪切并粘贴'一些内容

时间:2014-10-16 21:20:06

标签: xml xslt

背景

我的问题的更一般版本是recently posted,但由于帖子的质量,它没有收到回复。这是我的尝试!

我有以下要转换的XML结构

预处理XML

<schema>

    <!-- element to be imbedded -->

    <element name="tryCatch.catch">
        <complexType>
            <complexContent>
                <extension base="escalateContainer">
                    <attribute name="var" type="_var" />
                </extension>
            </complexContent>
        </complexType>
    </element>

    <complexType name="tryCatch">
        <complexContent>
            <extension base="scriptElement">
                <sequence>
                    <element name="try" type="escalateContainer" />
                    <element name="catch" type="tryCatch.catch" minOccurs="0" />
                    <element name="finally" type="escalateContainer" minOccurs="0" />
                </sequence>
            </extension>
        </complexContent>
    </complexType>

</schema>

...进入以下结构:

发布XSLT-Structure

<schema>

    <complexType name="tryCatch">
        <complexContent>
            <extension base="scriptElement">
                <sequence>
                    <element name="try" type="escalateContainer" />

                    <!-- Change here! -->

                    <element name="tryCatch.catch" minOccurs="0">
                        <complexType>
                            <complexContent>
                                <extension base="escalateContainer">
                                    <attribute name="var" type="_var" />
                                </extension>
                            </complexContent>
                        </complexType>

                    </element>
                    <element name="finally" type="escalateContainer" minOccurs="0" />
                </sequence>
            </extension>
        </complexContent>
    </complexType>

</schema>

流程概述

基本上,我只想

  1. 复制所有内容
  2. 然后找到{em} 中element complexType的所有.个孩子(通过构造 - 我确保此模式有效我的XML中的内容)。我的比赛的简化版本是:

      

    complexType.element.type = element.name

  3. 最后,将该元素替换为相应的全局元素。如果要替换的元素上的属性也被复制,则加分。

  4. 我到目前为止

    <xsl:template match="@* | node()">
    
            <xsl:copy>
    
                <xsl:apply-templates select="@* | node()" />
    
            </xsl:copy>
    
    </xsl:template>
    
    <xsl:template match="schema">
    
        <xsl:for-each select="element">
    
            <xsl:variable name="self" select="current()" />
    
            <xsl:variable name="name" select="@name" />
    
            <xsl:for-each select="/schema/complexType//element[@type=$name]">   
    
                <xsl:copy-of select="$self" />
    
            </xsl:for-each>         
    
        </xsl:for-each>
    
    </xsl:template>
    

    我认为我是正确的开始 - 使用身份模板复制所有内容,然后处理我想要更改的内容。问题是我的第二个模板返回复制的元素!这场比赛似乎很有效,我只是失去了我试图保留的所有其他内容。

1 个答案:

答案 0 :(得分:4)

一般来说for-each的使用并不是最好的主意。它使模板不灵活且难以阅读。 (当然有时你无法避免它,但在这种情况下它是可能的。)你应该使用apply-templates将迭代留给XSLT引擎。我会做这样的事情:

<xsl:template match="@* | node()" priority="-1"> <!-- copy everything unless another template with higher priority says otherwise -->
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
</xsl:template>

<xsl:template match="schema"> 
   <xsl:copy> <!-- copy the <schema> element -->
    <xsl:apply-templates select="complexType"/> <!-- copy all complexType elements within schema -->
   </xsl:copy>
</xsl:template>

<xsl:template match="element[contains(@type, '.')]"> <!-- if we encounter an <element> whose name contains the '.' character -->
        <xsl:variable name="type" select="@type" />
    <xsl:apply-templates select="//element[@name=$type]"/> <!-- copy the matching element instead -->
</xsl:template>

更新:我刚刚意识到我已将@type@name混为一谈,修正了此问题。