Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xslt 根据从引用列表收集的属性进行排序_Xslt_Xpath - Fatal编程技术网

Xslt 根据从引用列表收集的属性进行排序

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

我正在尝试使用XSLT2.0对分类的xml元素列表进行排序。每个元素都有一个唯一的ID,分类在包含这些元素和更多元素的另一个列表中定义。下面是一个启动XML文档的示例。我要排序的部分是/Atlas/VisitedCities。应根据世界范围和访问日期进行分类:

<?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”
,都没有区别,请参见规范,其中有很多示例,一个正式的定义,还有一个非正式的部分,例如“可以从右到左检查选择模式,如
书籍/章节/章节
。只有当节点是
元素时,它才会匹配此模式;然后,只有当它