从两个 xml 文件在 XSLT 中排序 [英] Sorting in XSLT from two xml files

查看:29
本文介绍了从两个 xml 文件在 XSLT 中排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这两个xml1> default.xml

I have these two xmls 1> default.xml

<UI-defination>
   <class >
      <list_view >
         <members>
            <member col_span="1" name="code" displayName="Code"/>
            <member col_span="1" name="creationTS" displayName="CreationTS"/>
            <member col_span="1" name="creator" displayName="Creator"/>
            <member col_span="1" name="displayName" displayName="DisplayName"/>
            <member col_span="1" name="emailAddress" displayName="EmailAddress"/>
            <member col_span="1" name="id" displayName="Id"/>
         </members>
      </list_view>
   </class>
</UI-defination>

2>Rules.xml

2>Rules.xml

<UI-defination>
    <class name="Role">
        <list_view multiselect="true">
            <members>
                <member name="displayName" sequence="3"/>
                <member name="code" sequence="4"/>
            </members>
            <exclude>
                <members>
                    <member name="id"/>
                    <member name="creator"/>
                </members>
            </exclude>
       </list_view>
    </class>
</UI-defination>

我想按照以下规则显示成员元素的列表

I want display list of member element according to following rules

  • rules.xml/members/member 应从列表中排除
  • 元素应该根据rules.xml中的sequence属性显示
  • 那些在 rules.xml/members/member 中不存在的元素应该按照它们在 default.xml 中的自然顺序显示.
    预期输出是....

    创作TS
    电子邮件地址
    显示名称
    代码

推荐答案

然后具有序列attr的元素,它们应该在那个准确的位置.然后空隙位置应该被自然填充剩余元素的顺序.(即通过没有的元素序列属性,来自 default.xml)

Then the elements which has sequence attr, they should be at that exact position. Then void position should get filled by the natural order of remaining element.(i.e. by the elements which don't have sequence attr., from default.xml)

恕我直言,这不是排序问题,而是排队问题.
让我们通过具有两种类型的成员来简化示例:已放置成员,其在队列中的位置是保留的,以及需要填充已放置成员之间的间隙的普通成员.

IMHO, this is not a sorting problem, but a queuing problem.
Let us simplify the example by having members of two types: placed members, whose place in the queue is reserved, and ordinary members that need to fill the gaps between the placed members.

<members>
    <member id="1" place="9"/>
    <member id="2" place="2"/>
    <member id="3" place="5"/>
    <member id="4"/>
    <member id="5"/>
    <member id="6"/>
    <member id="7"/>
    <member id="8"/>
    <member id="9"/>
    <member id="10"/>
    <member id="11"/>
    <member id="12"/>
</members>

排队算法可以描述如下:

The queuing algorithm could be described as follows:

  1. 保留成员按其保留位置排序.

  1. The reserved members are sorted by their reserved place.

每个预留成员呼叫"一组普通成员坐在它前面.

Each reserved member "calls" a group of ordinary members to be seated ahead of it.

在我们的示例中,我们在位置 2、5 和 9 保留了成员.之前9号位预留会员,我们需要叫3人一组普通会员坐在6、7、8号位.

In our example, we have reserved members at places 2, 5 and 9. Before seating the reserved member at place 9, we need to call a group of 3 ordinary members to be seated at places 6, 7 and 8.

这个组的大小等于组之间的差距大小当前成员的保留位置及其前任位置保留的兄弟姐妹.在我们的例子中是 9 - 5 - 1 = 3.

The size of this group is equal to the size of the gap between the current member's reserved place and the place of its preceding reserved sibling. That's 9 - 5 - 1 = 3 in our example.

这个组的起始位置可以推断如下:因为前一个成员的保留位置是#5,那么5个成员有已经就座;其中,2 名成员(在 #2 和 #5 位置)是保留成员,因此只有 3 个普通成员坐下,我们的小组从位置 5 - 3 + 1 = 4 开始.

The starting position of this group can be deduced as follows: since the preceding member's reserved place is #5, then 5 members have already been seated; out of these, 2 members (at places #2 and #5) are reserved members, therefore only 3 ordinary members have been seated and our group starts at position 5 - 3 + 1 = 4.

最后一个保留的成员调用其他普通成员在其后就座.

The last reserved member calls the rest of the ordinary members to be seated after it.

以下是 XSLT 1.0 中的实现示例:

Here's an example of implementation in XSLT 1.0:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="reserved-members">
    <xsl:for-each select="/members/member[@place]">
        <xsl:sort select="@place" data-type="number" order="ascending"/>
        <xsl:copy-of select="."/>
    </xsl:for-each>
</xsl:variable>

<xsl:variable name="ordinary-members" select="/members/member[not(@place)]"/>

<xsl:template match="/">
    <output>
        <xsl:for-each select="exsl:node-set($reserved-members)/member">

            <xsl:variable name="previous-place"> 
                <xsl:choose>
                    <xsl:when test="position()>1">
                        <xsl:value-of select="preceding-sibling::member[1]/@place"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="0"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>

            <xsl:variable name="gap-size" select="@place - $previous-place - 1"/>
            <xsl:variable name="gap-start" select="$previous-place - count(preceding-sibling::member) + 1"/> 

            <!-- fill the gap with ordinary members -->
            <xsl:for-each select="$ordinary-members[$gap-start &lt;= position() and position() &lt; $gap-start + $gap-size]">
                <xsl:copy-of select="."/>
            </xsl:for-each>

            <!-- output the reserved member -->
            <member id="{@id}" place="{@place}" start="{$gap-start}" size="{$gap-size}"/>

            <!-- output remaining ordinary members -->
            <xsl:if test="position()=last()">
                <xsl:for-each select="$ordinary-members[position() >= $gap-start + $gap-size]">
                    <xsl:copy-of select="."/>
                </xsl:for-each>
            </xsl:if>

        </xsl:for-each>
    </output>
</xsl:template>

</xsl:stylesheet>

当应用到上面的输入示例时,结果是:

When applied to the above input example, the result is:

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <member id="4"/>
   <member id="2" place="2" start="1" size="1"/>
   <member id="5"/>
   <member id="6"/>
   <member id="3" place="5" start="2" size="2"/>
   <member id="7"/>
   <member id="8"/>
   <member id="9"/>
   <member id="1" place="9" start="4" size="3"/>
   <member id="10"/>
   <member id="11"/>
   <member id="12"/>
</output>

这篇关于从两个 xml 文件在 XSLT 中排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆