对从参考列表收集的属性进行排序 [英] Sorting on attribute collected from reference list

查看:18
本文介绍了对从参考列表收集的属性进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 XSLT 2.0 对已分类的 xml 元素列表进行排序.每个元素都有一个唯一的 ID,分类在包含这些和更多元素的另一个列表中定义.下面是一个起始 XML 文档的示例.我想要排序的部分是/Atlas/VisitedCities.应该按照世界区域和访问日期排序:

I am trying to sort a list of categorized xml elements, using XSLT 2.0. Each element has a unique ID and the categorization is defined in another list containing these and more elements. Here's an example of a starting XML document. The section that I want sorted is /Atlas/VisitedCities. It should be sorted according to area of the world and date of the visit:

<?xml version="1.0" encoding="UTF-8"?>
<Atlas>
    <Cities>
        <City id="1" worldPart="Africa">
            <Name>Luxor</Name>
            <Founded>-3200</Founded>
            <Location>Egypt</Location>
        </City>
        <City id="2" worldPart="Africa">
            <Name>Tripoli</Name>
            <Founded>-700</Founded>
            <Location>Libya</Location>
        </City>
        <City id="3" worldPart="Americas">
            <Name>Cholula</Name>
            <Founded>-200</Founded>
            <Location>Mexico</Location>
        </City>
        <City id="4" worldPart="Americas">
            <Name>Flores</Name>
            <Founded>-1000</Founded>
            <Location>Guatemala</Location>
        </City>
        <City id="5" worldPart="Europe">
            <Name>Argos</Name>
            <Founded>-5000</Founded>
            <Location>Greece</Location>
        </City>
        <City id="6" worldPart="Europe">
            <Name>Athens</Name>
            <Founded>-4000</Founded>
            <Location>Greece</Location>
        </City>
    </Cities>
    <VisitedCities lastUpdate="2018-09-10">
        <VisitedCity cityID="6">
            <Date>1883-08-26</Date>
            <Visitor>Dora</Visitor>
        </VisitedCity>
        <VisitedCity cityID="3">
            <Date>1907-01-02</Date>
            <Visitor>Nemo</Visitor>
        </VisitedCity>
        <VisitedCity cityID="4">
            <Date>1940-02-08</Date>
            <Visitor>Jimenez</Visitor>
        </VisitedCity>
        <VisitedCity cityID="2">
            <Date>1886-06-10</Date>
            <Visitor>James T. Kirk</Visitor>
        </VisitedCity>
    </VisitedCities>
</Atlas>

想要的输出是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<Atlas>
    <Cities>
        <City id="1" worldPart="Africa">
            <Name>Luxor</Name>
            <Founded>-3200</Founded>
            <Location>Egypt</Location>
        </City>
        <City id="2" worldPart="Africa">
            <Name>Tripoli</Name>
            <Founded>-700</Founded>
            <Location>Libya</Location>
        </City>
        <City id="3" worldPart="Americas">
            <Name>Cholula</Name>
            <Founded>-200</Founded>
            <Location>Mexico</Location>
        </City>
        <City id="4" worldPart="Americas">
            <Name>Flores</Name>
            <Founded>-1000</Founded>
            <Location>Guatemala</Location>
        </City>
        <City id="5" worldPart="Europe">
            <Name>Argos</Name>
            <Founded>-5000</Founded>
            <Location>Greece</Location>
        </City>
        <City id="6" worldPart="Europe">
            <Name>Athens</Name>
            <Founded>-4000</Founded>
            <Location>Greece</Location>
        </City>
    </Cities>
    <VisitedCities lastUpdate="2018-09-10">
        <VisitedCity cityID="2">
            <Date>1886-06-10</Date>
            <Visitor>James T. Kirk</Visitor>
        </VisitedCity>
        <VisitedCity cityID="6">
            <Date>1883-08-26</Date>
            <Visitor>Dora</Visitor>
        </VisitedCity>
        <VisitedCity cityID="3">
            <Date>1907-01-02</Date>
            <Visitor>Nemo</Visitor>
        </VisitedCity>
        <VisitedCity cityID="4">
            <Date>1940-02-08</Date>
            <Visitor>Jimenez</Visitor>
        </VisitedCity>
    </VisitedCities>
</Atlas>

我正在努力处理的样式表 (XSLT 2.0) 看起来像这样:

The stylesheet (XSLT 2.0) that I am struggling with looks like this:

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

    <!-- Format output -->
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*" />

    <!-- Copy everything that does not match later templates. -->
    <xsl:template match="node()|@*" priority="-1">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:variable name="city.list" select="/Atlas/Cities"/>

    <xsl:variable name="sort-order" as="element()*">
        <wPart>Africa</wPart>
        <wPart>Europe</wPart>
        <wPart>Americas</wPart>
    </xsl:variable>

    <xsl:template match="/Atlas/VisitedCities">
        <xsl:variable name="city-list" select="."/>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:for-each select="$sort-order">
                <xsl:variable name="this-wpart" select="./text()"/>
                <!-- How to select VisitedCity based on info in other list??? -->
                <xsl:apply-templates select="$city-list/VisitedCity[$city.list/City[@cityID=$city-list/VisitedCity/@cityID]/@worldPart=$this-wpart]">
                    <xsl:sort select="./Date"/>
                </xsl:apply-templates>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

我想我明白为什么这个样式表不起作用(它根本不排序),因为我不知道如何在(最后一个)应用模板中进行选择.我不知道如何从这个表达式的内部引用最外面的元素.

I think I understand why this stylesheet will not work (it does not sort at all), as I don't know how to make the selection in the (last) apply-templates. I don't see how to refer to the outermost elements from the inner parts of this expression.

推荐答案

通过 id 属性设置一个键来引用 City 元素就足够了, 在 xsl:sort select 表达式中引用 worldPart 属性.此外,您可以将大陆订单上的 for-each 替换为带有

It might suffice to set up a key to reference the City elements by the id attribute to then, in the xsl:sort select expression reference the worldPart attribute. Additionally you could replace the for-each on your continent order with an index-of() call with

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="city-by-id" match="Cities/City" use="@id"/>

    <xsl:variable name="sort-order" as="element()*">
        <wPart>Africa</wPart>
        <wPart>Europe</wPart>
        <wPart>Americas</wPart>
    </xsl:variable>

  <xsl:template match="VisitedCities">
      <xsl:copy>
          <xsl:apply-templates select="VisitedCity">
              <xsl:sort select="index-of($sort-order, key('city-by-id', @cityID)/@worldPart)"/>
              <xsl:sort select="Date"/>
          </xsl:apply-templates>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/eiZQaFJ

该完整示例是 XSLT 3,但要将其与 XSLT 2 一起使用,您只需将其中的 xsl:mode 声明替换为您的模板,您的模板前面带有注释 <!-- 复制与以后模板不匹配的所有内容.-->,即带有身份转换模板.

That complete example is XSLT 3 but to use it with XSLT 2 you would just replace the xsl:mode declaration in there with your template you have prefixed with the comment <!-- Copy everything that does not match later templates. -->, that is, with the identity transformation template.

这篇关于对从参考列表收集的属性进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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