Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.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
Xml XSLT-对逗号分隔字符串重新排序_Xml_Xslt_Sorting_Xslt 2.0 - Fatal编程技术网

Xml XSLT-对逗号分隔字符串重新排序

Xml XSLT-对逗号分隔字符串重新排序,xml,xslt,sorting,xslt-2.0,Xml,Xslt,Sorting,Xslt 2.0,我希望有人能帮忙。我有一个逗号分隔的字符串,如A10、A12、A11、S10、S11、S12这需要重新排序为S10、A10、S11、A11、S12、A12 排序标准如下: 每次都是在A之前 年数的增长顺序是10年前9年前11年前12年前13年等 因此,对于输入XML: <root> <row>A10,A12,A11,S10,S11,S12</row> </root> A10,A12,A11,S10,S11,S12 期望输出: &l

我希望有人能帮忙。我有一个逗号分隔的字符串,如
A10、A12、A11、S10、S11、S12
这需要重新排序为
S10、A10、S11、A11、S12、A12

排序标准如下:

  • 每次都是在A之前
  • 年数的增长顺序是10年前9年前11年前12年前13年等
因此,对于输入XML:

<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>

A10,A12,A11,S10,S11,S12
期望输出:

<root>
    <row>S10,A10,S11,A11,S12,A12</row>
</root>

S10、A10、S11、A11、S12、A12
在2.0中:

<xsl:perform-sort select="tokenize(row, ',')">
  <xsl:sort select="xs:integer(substring(., 2))"/>
  <xsl:sort select="substring(., 1, 1)" order="descending"/>
</xsl:perform-sort>

在2.0中:

<xsl:perform-sort select="tokenize(row, ',')">
  <xsl:sort select="xs:integer(substring(., 2))"/>
  <xsl:sort select="substring(., 1, 1)" order="descending"/>
</xsl:perform-sort>

请注意:

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>
这个问题中的需求不包括某些可能的输入,因此,Michael Kay的两个当前解决方案和这个解决方案可以产生不同的结果

前者产生的结果总是按数字排序(并且可能违反交替的
S
a
要求)

此解决方案产生的结果是,
S
a
始终按此顺序交替,但可能并不总是满足数字排序要求

示例1

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>
迈克尔·凯的解决方案产生了

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>
这里“总是在(交替)之前”的要求没有得到满足

当前解决方案产生以下结果:

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>
这里满足了替换要求,但没有满足数字排序要求


此转换

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>

应用于提供的XML文档时

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>

A10,A12,A11,S10,S11,S12
生成所需的正确结果:

<root>
   <row>S10,A10,S11,A11,S12,A12</row>
</root>

S10、A10、S11、A11、S12、A12

请注意:

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>
这个问题中的需求不包括某些可能的输入,因此,Michael Kay的两个当前解决方案和这个解决方案可以产生不同的结果

前者产生的结果总是按数字排序(并且可能违反交替的
S
a
要求)

此解决方案产生的结果是,
S
a
始终按此顺序交替,但可能并不总是满足数字排序要求

示例1

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>
迈克尔·凯的解决方案产生了

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>
这里“总是在(交替)之前”的要求没有得到满足

当前解决方案产生以下结果:

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>
这里满足了替换要求,但没有满足数字排序要求


此转换

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>

应用于提供的XML文档时

A8,A10,A12,A11,S9,S10,S11,S12
A8,S9,S10,A10,S11,A11,S12,A12
S9,A8,S10,A10,S11,A11,S12,A12
<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vTokens" select="tokenize(/*/row, ',')"/>

    <xsl:variable name="vASeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'A')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

    <xsl:variable name="vSSeq" as="xs:string*">
     <xsl:perform-sort select="$vTokens[starts-with(.,'S')]">
      <xsl:sort select="substring(.,2)" data-type="number"/>
     </xsl:perform-sort>
    </xsl:variable>

 <xsl:template match="/">
     <root>
      <row>
        <xsl:sequence select=
        "string-join(
                     (for $i in 1 to count($vSSeq)
                        return
                          ($vSSeq[$i], $vASeq[$i])
                      ),
                      ','
                           )
        "/>
      </row>
     </root>
 </xsl:template>
</xsl:stylesheet>
<root>
    <row>A10,A12,A11,S10,S11,S12</row>
</root>

A10,A12,A11,S10,S11,S12
生成所需的正确结果:

<root>
   <row>S10,A10,S11,A11,S12,A12</row>
</root>

S10、A10、S11、A11、S12、A12

MMKD,这两个要求可能是矛盾的。例如,如果我们有
A9、A10、A12、A11、S10、S11、S12
并且希望数值部分在结果中按递增顺序排列,那么
A9
将出现在任何
Sn
之前。请解释这种情况下的预期结果是什么?这不是问题,因为只有一个
9
。只要9在10之前,这就不是问题。第一个排序应该是年,所以
9、10、11、12
然后第二个排序应该是
S然后N
。我可能更容易将其转换……A9=“秋2009”和S10=“夏季2010”这样,即使S应该在A之前,但由于year.MMKD的原因,这两个要求可能是矛盾的。例如,如果我们有
A9、A10、A12、A11、S10、S11、S12
,并且希望结果中的数字部分按递增顺序排列,那么
A9
将出现在任何
Sn
之前。请解释一下在这种情况下,预期结果是什么?这不是问题,因为只有一个
9
。只要9在10之前,这就不是问题。第一个排序应该是年,所以
9,10,11,12
然后第二个排序应该是
S然后N
。我可能更容易转换它……A9=“Autumn2009”和S10=“Summer2010”这样的话,你会认为S10之前是A9,尽管S应该在A之前,因为今年。