我试图搜索类似的问题,发现这个和这个。但是它们特别不符合我的要求。
示例XML Input with:
<TestMessage>
<INSTest>
<INSClaim Id="1-TEST">
<Id>1-TEST</Id>
<INSTestElements>
<INSTestElement>
<SortingOrder>2</SortingOrder>
<Created>12/29/2012 13:45:58</Created>
<Id>1-Element1</Id>
</INSTestElement>
<INSTestElement>
<SortingOrder>3</SortingOrder>
<Created>12/31/2012 14:45:58</Created>
<Id>1-Element2</Id>
</INSTestElement>
<INSTestElement>
<SortingOrder>1</SortingOrder>
<Created>12/31/2011 21:45:58</Created>
<Id>1-Element3</Id>
</INSTestElement>
</INSTestElements>
</INSClaim>
</INSTest>
</TestMessage>
XSL input tried with:
<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="INSTestElements">
<xsl:copy>
<xsl:for-each select="INSTestElement">
<xsl:variable name="created"><xsl:value-of select="Created"/></xsl:variable>
<xsl:variable name="created_date" select="substring-before($created, ' ')"/>
<xsl:variable name="year" select="substring($created_date, string-length($created_date) -3)"/>
<xsl:variable name="day" select="substring-before($created_date, '/')"/>
<xsl:variable name="month" select="format-number(substring-before(substring-after($created_date, $day), $year), '00')"/>
<xsl:copy>
<xsl:apply-templates>
<xsl:sort select="$year" data-type="number"/>
<xsl:sort select="$month" data-type="number"/>
<xsl:sort select="$day" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出:
<?xml version="1.0" encoding="UTF-8"?>
<TestMessage>
<INSTest>
<INSClaim Id="1-TEST">
<Id>1-TEST</Id>
<INSTestElements>
<INSTestElement>
<SortingOrder>2</SortingOrder>
<Created>12/29/2012 13:45:58</Created>
<Id>1-Element1</Id>
</INSTestElement>
<INSTestElement>
<SortingOrder>3</SortingOrder>
<Created>12/31/2012 14:45:58</Created>
<Id>1-Element2</Id>
</INSTestElement>
<INSTestElement>
<SortingOrder>1</SortingOrder>
<Created>12/31/2011 21:45:58</Created>
<Id>1-Element3</Id>
</INSTestElement>
</INSTestElements>
</INSClaim>
</INSTest>
</TestMessage>
预期输出:<?xml version="1.0" encoding="UTF-8"?>
<TestMessage>
<INSTest>
<INSClaim Id="1-TEST">
<Id>1-TEST</Id>
<INSTestElements>
<INSTestElement>
<SortingOrder>1</SortingOrder>
<Created>12/31/2011 21:45:58</Created>
<Id>1-Element3</Id>
</INSTestElement>
<INSTestElement>
<SortingOrder>2</SortingOrder>
<Created>12/29/2012 13:45:58</Created>
<Id>1-Element1</Id>
</INSTestElement>
<INSTestElement>
<SortingOrder>3</SortingOrder>
<Created>12/31/2012 14:45:58</Created>
<Id>1-Element2</Id>
</INSTestElement>
</INSTestElements>
</INSClaim>
</INSTest>
</TestMessage>
我猜我正在做的错误是,我试图将sort
应用于INSTestElement
的子元素,因为我必须将其应用于INSTestElement
本身。我试着在我开发的代码中变换代码块,但是没有任何成果。相反,我发现错误说invalid element variable under apply-templates
我主要关心的是如何提取日期created
的值,我必须使用它来排序它的父INSTestElement
..
变化
<xsl:for-each select="INSTestElement">
<xsl:variable name="created"><xsl:value-of select="Created"/></xsl:variable>
<xsl:variable name="created_date" select="substring-before($created, ' ')"/>
<xsl:variable name="year" select="substring($created_date, string-length($created_date) -3)"/>
<xsl:variable name="day" select="substring-before($created_date, '/')"/>
<xsl:variable name="month" select="format-number(substring-before(substring-after($created_date, $day), $year), '00')"/>
<xsl:copy>
<xsl:apply-templates>
<xsl:sort select="$year" data-type="number"/>
<xsl:sort select="$month" data-type="number"/>
<xsl:sort select="$day" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:for-each>
<xsl:apply-templates select="INSTestElement">
<xsl:sort select="substring(substring-after(substring-after(Created, '/'), '/'), 1, 4)" data-type="number"/>
<xsl:sort select="substring(Created, 1, 2)" data-type="number"/>
<xsl:sort select="substring-before(substring-after(Created, '/'), '/')" data-type="number"/>
</xsl:apply-templates>
未经测试,但应该显示使用方法(即将模板应用于那些INSTestElement
元素并在此过程中进行排序)。xsl:sort select
表达式可能需要一些调整,但是您知道输入日期的格式,这主要是选择正确部分的问题。
感谢Martin的好建议。将模板INSTestElements
代码替换为下面的代码。现在它根据Created
字段的datetime值升序排序。
<xsl:template match="INSTestElements">
<xsl:copy>
<xsl:apply-templates select="INSTestElement">
<xsl:sort select="substring(substring-after(substring-after(Created, '/'), '/'), 1, 4)" data-type="number"/>
<xsl:sort select="substring(Created, 1, 2)" data-type="number"/>
<xsl:sort select="substring-before(substring-after(Created, '/'), '/')" data-type="number"/>
<xsl:sort select="substring-before(substring-after(Created, ' '), ':')"/>
<xsl:sort select="substring-before(substring-after(Created, ':'), ':')"/>
<xsl:sort select="substring-after(substring-after(Created, ':'), ':')"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>