Xslt 根据从引用列表收集的属性进行排序
我正在尝试使用XSLT2.0对分类的xml元素列表进行排序。每个元素都有一个唯一的ID,分类在包含这些元素和更多元素的另一个列表中定义。下面是一个启动XML文档的示例。我要排序的部分是/Atlas/VisitedCities。应根据世界范围和访问日期进行分类:Xslt 根据从引用列表收集的属性进行排序,xslt,xpath,Xslt,Xpath,我正在尝试使用XSLT2.0对分类的xml元素列表进行排序。每个元素都有一个唯一的ID,分类在包含这些元素和更多元素的另一个列表中定义。下面是一个启动XML文档的示例。我要排序的部分是/Atlas/VisitedCities。应根据世界范围和访问日期进行分类: <?xml version="1.0" encoding="UTF-8"?> <Atlas> <Cities> <City id="1" worldPart="Africa
<?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>
卢克索
-3200
埃及
的黎波里
-700
利比亚
丘鲁拉
-200
墨西哥
弗洛雷斯
-1000
危地马拉
阿尔戈斯
-5000
希腊
雅典
-4000
希腊
1883-08-26
多拉
1907-01-02
尼莫
1940-02-08
希门尼斯
1886-06-10
詹姆斯·柯克
想要的输出是:
<?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>
卢克索
-3200
埃及
的黎波里
-700
利比亚
丘鲁拉
-200
墨西哥
弗洛雷斯
-1000
危地马拉
阿尔戈斯
-5000
希腊
雅典
-4000
希腊
1886-06-10
詹姆斯·柯克
1883-08-26
多拉
1907-01-02
尼莫
1940-02-08
希门尼斯
我正在处理的样式表(XSLT 2.0)如下所示:
<?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>
非洲
欧洲
美洲
我想我理解为什么这个样式表不起作用(它根本不排序),因为我不知道如何在(最后一个)应用模板中进行选择。我不知道如何从表达式的内部引用最外面的元素。设置一个键,通过
id
属性引用City
元素就足够了,然后在xsl:sort
中选择表达式引用worldPart
属性。此外,您还可以使用index-of()
调用替换大陆订单上每个的
<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>
非洲
欧洲
美洲
完整的示例是XSLT 3,但要将其与XSLT 2一起使用,只需将其中的xsl:mode
声明替换为前缀为注释
的模板即可,使用身份转换模板。只需设置一个键,通过id
属性引用City
元素,然后在xsl:sort
中选择表达式引用worldPart
属性即可。此外,您还可以使用index-of()
调用替换大陆订单上每个的
<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>
非洲
欧洲
美洲
完整的示例是XSLT 3,但要将其与XSLT 2一起使用,您只需将其中的xsl:mode
声明替换为前缀为注释
的模板,即标识转换模板。是否可以编辑您的问题,以显示您期望的输出?非常感谢。您需要用通俗易懂的英语解释,并且在输出示例中,您希望根据哪些标准对哪个部分进行排序,您的XSLT不起作用(match=“/VisitiedCities”
甚至与您的示例的Atlas
root)不匹配。您可以编辑您的问题吗,要显示您期望的输出,请?非常感谢。您需要用通俗易懂的英语解释,并且在输出示例中,您希望根据哪些标准对哪个部分进行排序,您的XSLT不起作用(match=“/VisitiedCities”
甚至与您的示例的Atlas
root)不匹配。我不知道您可以匹配“VisitedCities”或“Cities/City”。为什么不需要前导“/Atlas/”或“/”?如果相应的路径表达式将选择某个节点(或XSLT 3中的一般项),则匹配模式将匹配该节点,请参阅章节和。虽然您可以编写更具体的模式,并且对于您的示例,使用从根目录向下的绝对路径,例如match=“/Atlas/Cities/City”
或match=“/Atlas/visitedcity”
,但在匹配模式中,通常尽可能短,并根据需要尽可能具体。是“visitedcity”吗“不同于”//访问过的城市”在任何方面?在我看来,在这两种情况下都必须搜索整个树。在马赫模式中,无论您是编写match=“VisitedCities”
还是match=“///VisitedCities”
,都没有区别,请参见规范,其中有很多示例,一个正式的定义,还有一个非正式的部分,例如“可以从右到左检查选择模式,如书籍/章节/章节
。只有当节点是节
元素时,它才会匹配此模式;然后,只有当它