XSLT - 将最后一个元素移动到指定元素之上

时间:2017-10-27 11:38:20

标签: xml xslt

我的输入就像是,

<meta>
...................
...................
<doctitle>Pocket Atlas of Sectional Anatomy</doctitle>
<docsubtitle>Computed Tomography and Magnetic Resonance Imaging</docsubtitle>
<docdate type="released">2017-10-27</docdate>
<relatedobjects>
    <relpdfio/>
</relatedobjects>
<publisher>
    <address>
    <street>333 Seventh Ave.</street>
    ......
</address>
</publisher>
<version type="print">4th Edition</version>
</meta>

输出应该是,

<meta>
...................
...................
<doctitle>Pocket Atlas of Sectional Anatomy</doctitle>
<docsubtitle>Computed Tomography and Magnetic Resonance Imaging</docsubtitle>
<docdate type="released">2017-10-27</docdate>
<version type="print">4th Edition</version>
<relatedobjects>
    <relpdfio/>
</relatedobjects>
<publisher>
    <address>
    <street>333 Seventh Ave.</street>
    ......
</address>
</publisher>
</meta>

我们希望移动&#34;版本&#34; &#34; docdate&#34;之后的元素元素。在这种情况下,我会混淆写XSLT。你能指导我们吗?

3 个答案:

答案 0 :(得分:1)

可能有一个最佳解决方案,而不是下面发布的解决方案,但这是你可以尝试的。如果有更多的元素,那么按顺序排列它们会变得很复杂,因为订单是在变量中预先定义的。

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

    <xsl:variable name="elementOrder" select="'|doctitle|docsubtitle|docdate|version|relatedobjects|publisher|'" />

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

    <xsl:template match="meta">
        <xsl:copy>
            <xsl:apply-templates select="*">
                <xsl:sort select="substring-before($elementOrder, concat('|',name(),'|'))" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

这是另一种方法......

从身份模板开始..

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

要在version之后复制docdate,请在匹配docdate的模板中执行此操作(我在此假设XSLT 2.0)

<xsl:template match="docdate">
    <xsl:next-match />
    <xsl:copy-of select="../version" />
</xsl:template>

然后您需要确保version也不会被复制到其原始位置......

<xsl:template match="version" />

试试这个XSLT

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

    <xsl:template match="version" />

    <xsl:template match="docdate">
        <xsl:next-match />
        <xsl:copy-of select="../version" />
    </xsl:template>

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

答案 2 :(得分:0)

所以你只想移动那个节点,每个元素总有一个版本? 在这种情况下试试这个:

<xsl:template match="@*|node()[local-name() != 'version']">
    <xsl:choose>
        <xsl:when test="local-name() = 'docdate'">
            <xsl:copy>
                <xsl:apply-templates/>
            </xsl:copy>
            <xsl:copy>
                <xsl:value-of select="following::version"/>
            </xsl:copy>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy>
                <xsl:apply-templates/>
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

我不确定它是否会复制属性。