给出以下的XML片段:
<forms>
<FORM lob="BO" form_name="AI OM 10"/>
<FORM lob="BO" form_name="CL BP 03 01"/>
<FORM lob="BO" form_name="AI OM 107"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="123 DDE"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="AI OM 98"/>
</forms>
我需要按字母顺序按FORM_name对FORM节点进行排序,以便将form_name中包含“AI OM”的所有表单组合在一起,然后在整数范围内按整数的数字顺序排列(对于其他表单也是如此)。
form_name可以是开放季节,因为字母和数字可以是任何顺序:
XX ## ##
XX XX ##
XX XX ###
XX XX ## ##
XX ###
XX XXXX
'## XXX
XXX ###
我认为需要发生的是字符串需要在字母和数字之间分割。数字部分可能会按照我想的任何空格排序。
我不知道如何拆分字符串,然后覆盖所有排序/分组组合,因为“form_name”格式没有规则。
我们正在使用XSLT 2.0。感谢。
答案 0 :(得分:3)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vDigits" select="'0123456789 '"/>
<xsl:variable name="vAlpha" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ '"/>
<xsl:template match="/*">
<forms>
<xsl:for-each select="FORM">
<xsl:sort select="translate(@form_name,$vDigits,'')"/>
<xsl:sort select="translate(@form_name,$vAlpha,'')"
data-type="number"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</forms>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<forms>
<FORM lob="BO" form_name="AI OM 10"/>
<FORM lob="BO" form_name="CL BP 03 01"/>
<FORM lob="BO" form_name="AI OM 107"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="123 DDE"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="AI OM 98"/>
</forms>
生成想要的正确结果:
<forms>
<FORM lob="BO" form_name="AI OM 10"/>
<FORM lob="BO" form_name="AI OM 98"/>
<FORM lob="BO" form_name="AI OM 107"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="CL BP 03 01"/>
<FORM lob="BO" form_name="123 DDE"/>
</forms>
请注意:
两条<xsl:sort>
条指令实施了两阶段排序
XPath translate()
函数用于生成仅alpha排序键或仅数位排序键。
答案 1 :(得分:0)
此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="forms">
<xsl:apply-templates>
<xsl:sort select="normalize-space(
translate(@form_name,
'0123456789',
''))"/>
<xsl:sort select="substring-before(
concat(
normalize-space(
translate(@form_name,
translate(@form_name,
'0123456789 ',
''),
'')),
' '),' ')" data-type="number"/>
<xsl:sort select="substring-after(
normalize-space(
translate(@form_name,
translate(@form_name,
'0123456789 ',
''),
'')),
' ')" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
输出:
<FORM lob="BO" form_name="AI OM 10"></FORM>
<FORM lob="BO" form_name="AI OM 98"></FORM>
<FORM lob="BO" form_name="AI OM 107"></FORM>
<FORM lob="BO" form_name="CL BP 00 02"></FORM>
<FORM lob="BO" form_name="CL BP 00 02"></FORM>
<FORM lob="BO" form_name="CL BP 03 01"></FORM>
<FORM lob="BO" form_name="123 DDE"></FORM>
XSLT 2.0解决方案:此样式表
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="forms">
<xsl:apply-templates>
<xsl:sort select="string-join(tokenize(@form_name,' ')
[not(. castable as xs:integer)],
' ')"/>
<xsl:sort select="xs:integer(tokenize(@form_name,' ')
[. castable as xs:integer][1])"/>
<xsl:sort select="xs:integer(tokenize(@form_name,' ')
[. castable as xs:integer][2])"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:0)
应该注意的是,标记的答案在所有情况下都不起作用。
输入:
<forms>
<FORM lob="BO" form_name="AA 11 AB"/>
<FORM lob="BO" form_name="AA AZ 01"/>
</forms>
预期产出:
<forms>
<FORM lob="BO" form_name="AA AZ 01"/>
<FORM lob="BO" form_name="AA 11 AB"/>
</forms>
实际输出:
<forms>
<FORM lob="BO" form_name="AA 11 AB"/>
<FORM lob="BO" form_name="AA AZ 01"/>
</forms>
如果在数字后面允许使用字母,则不能在第一个排序键中删除它们。