订购一些 XML 个节点

Ordering some XML nodes

我正在使用 XSLT 1.0

我有一条要转换的输入消息。这个输入消息由4类节点A、B、Order、Article组成。喜欢这个:

A
B
Order0
Article100
Article102
A
B
Order1
Article101
A
B
A
B
A
B
etc

我的目标是把A和B节点放在消息的开头,所以我有:

A
B
A
B
A
B
A
B
A
B
Order0
Article100
Article102
Order1
Article101

所以这是我的例子:

输入

<Messages>
    <Message>
        <A>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </A>
    </Message>
    <Message>
        <B>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </B>
    </Message>
    <Message>
        <Order>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Order>
    </Message>
    <Message>
        <Article>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Article>
    </Message>
    <Message>
        <Article>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Article>
    </Message>
    <Message>
        <A>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </A>
    </Message>
    <Message>
        <B>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </B>
    </Message>
    <Message>
        <Order>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Order>
    </Message>
    <Message>
        <Article>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Article>
    </Message>
    <Message>
        <A>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </A>
    </Message>
    <Message>
        <B>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </B>
    </Message>
</Messages>

输出

<Messages>
    <Message>
        <A>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </A>
    </Message>
    <Message>
        <B>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </B>
    </Message>
    <Message>
        <A>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </A>
    </Message>
    <Message>
        <B>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </B>
    </Message>
    <Message>
        <A>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </A>
    </Message>
    <Message>
        <B>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </B>
    </Message>
    <Message>
        <Order>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Order>
    </Message>
    <Message>
        <Article>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Article>
    </Message>
    <Message>
        <Article>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Article>
    </Message>
    <Message>
        <Order>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Order>
    </Message>
    <Message>
        <Article>
            <SomeData>somedata</SomeData>
            <SomeData2>somedata</SomeData2>
        </Article>
    </Message>
</Messages>

不幸的是,我在使用旧版本的 Biztalk 时受到 xslt 1.0 的限制。 我考虑过可能使用 order by,但只针对那些 A 和 B 节点。

如果你真的只有这些元素需要排序,你可以简单地直接命名它们,像这样:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>
  
  <!-- Identity transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Messages">
      <xsl:copy>
        <xsl:apply-templates select="Message[A or B]"/>
        <xsl:apply-templates select="Message[not(A) and not(B)]"/>
      </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

看到它在这里工作:https://xsltfiddle.liberty-development.net/gVrvcy1/1

如果你想通过排序来做到这一点,你可以这样做:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/Messages">
    <xsl:copy>
        <xsl:for-each select="Message">
            <xsl:sort select="number(A or B)" data-type="number" order="descending"/>
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>