我正在尝试通过数据属性获取XML数据和排序元素。不幸的是,日期以mm / dd / yyyy格式出现,并不是静态长度。 (Jan = 1而不是01)所以我认为字符串必须被解析为三个组件并填充月份。新结合的值(yyyymmdd)然后按降序排序。
问题是我不知道该怎么做。以下是数据的示例
<content date="1/13/2011 1:21:00 PM">
<collection vo="promotion">
<data vo="promotion" promotionid="64526" code="101P031" startdate="1/7/2011 12:00:00 AM" type="base"/>
<data vo="promotion" promotionid="64646" code="101P026" startdate="2/19/2011 12:00:00 AM" type=""/>
<data vo="promotion" promotionid="64636" code="101P046" startdate="1/9/2011 12:00:00 AM" type="base"/>
</collection>
</content>
也有人可以推荐一本关于学习XSLT的好书吗?
谢谢!
我真的希望我能更好地理解这个LOL无论如何,我使用了你提供的代码,并添加了在你提供的相关代码中工作的'value-of'代码,并且看不到任何结果。理想情况下,一旦对其进行了排序,我就需要从最新的数据元素中引用多个其他属性。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="vrtfPass1">
<xsl:apply-templates/>
</xsl:variable>
<xsl:apply-templates mode="pass2" select=
"ext:node-set($vrtfPass1)/*"/>
</xsl:template>
<xsl:template match="@startdate">
<xsl:variable name="vDate" select="substring-before(.,' ')"/>
<xsl:variable name="vYear" select=
"substring($vDate, string-length($vDate) -3)"/>
<xsl:variable name="vDayMonth" select=
"substring-before($vDate, concat('/',$vYear))"/>
<xsl:variable name="vMonth"
select="format-number(substring-before($vDayMonth, '/'), '00')"/>
<xsl:variable name="vDay"
select="format-number(substring-after($vDayMonth, '/'), '00')"/>
<xsl:attribute name="startdate">
<xsl:value-of select="concat($vYear,$vMonth,$vDay)"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="node()|@*" mode="pass2">
<xsl:copy>
<xsl:apply-templates mode="pass2" select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="pass2" match="collection">
<xsl:copy>
<xsl:apply-templates mode="pass2" select="@*"/>
<xsl:apply-templates mode="pass2">
<xsl:sort select="@startdate"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="content/collection/data">
<xsl:if test="position()=1">
<xsl:value-of select="@promotionid"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
...
</xsl:template>
<xsl:template mode="pass2" match="content/collection/data">
<xsl:value-of select="@promotionid"/>
</xsl:template>
</xsl:stylesheet>
我仍然没有得到任何输出。我google了一下,并尝试搞乱这个声明xmlns:ext="http://exslt.org/common"
并根据我看过的文章尝试了不同的值。我试过了
没有提供输出。所以我想知道我是否有问题,或者我的xslt处理器是否支持它。
好吧,显然我们已经多次获得了不良信息。我用另一个属性更新了示例XML,这个属性改变了需要做的事情。
需要发生的是按照我们已经完成的日期对数据进行排序,然后拉出最新的数据节点的promotionid并且type ='base'。如果没有数据节点具有type ='base',那么我们只是引用最新的数据节点,就像我们已经有效一样。
希望这是有道理的。再一次非常感谢。
答案 0 :(得分:1)
您可以使用此样式表中的多个xsl:sort
说明:
<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="collection">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="data">
<xsl:sort select="substring-after(
substring-after(
substring-before(
@startdate,
' '),
'/'),
'/')" data-type="number"/>
<xsl:sort select="substring-before(
@startdate,
'/')" data-type="number"/>
<xsl:sort select="substring-before(
substring-after(
@startdate,
'/'),
'/')" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出:
<content date="1/13/2011 1:21:00 PM">
<collection vo="promotion">
<data vo="promotion" promotionid="64526" code="101P031"
startdate="1/7/2011 12:00:00 AM"></data>
<data vo="promotion" promotionid="64636" code="101P046"
startdate="1/9/2011 12:00:00 AM"></data>
<data vo="promotion" promotionid="64646" code="101P026"
startdate="2/19/2011 12:00:00 AM"></data>
</collection>
</content>
从评论中更新
我正在努力做的就是这样 样式表按您的方式执行排序 完成后再导出 使用startdate升级项目 在这种情况下,“
2/19/2011
”。我以为 它会是这样的<xsl:value-of select="data[last()]/@promotionid"/>
但我要么在错误中使用它 放置或声明错误
更新3 :现在有了新的选择数据条件
使用“标准”最大成语。这个样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="collection">
<xsl:variable name="vData" select="data[@type='base']"/>
<xsl:for-each select="data[not($vData)]|$vData">
<xsl:sort select="substring-after(
substring-after(
substring-before(
@startdate,
' '),
'/'),
'/')" data-type="number"/>
<xsl:sort select="substring-before(
@startdate,
'/')" data-type="number"/>
<xsl:sort select="substring-before(
substring-after(
@startdate,
'/'),
'/')" data-type="number"/>
<xsl:if test="position()=last()">
<xsl:value-of select="@promotionid"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
输出:
64636
答案 1 :(得分:0)
以下是使用2遍转换进行排序的一种方法(可以在一次转换中执行此操作,但代码太复杂了):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="vrtfPass1">
<xsl:apply-templates/>
</xsl:variable>
<xsl:apply-templates mode="pass2" select=
"ext:node-set($vrtfPass1)/*"/>
</xsl:template>
<xsl:template match="@startdate">
<xsl:variable name="vDate" select="substring-before(.,' ')"/>
<xsl:variable name="vYear" select=
"substring($vDate, string-length($vDate) -3)"/>
<xsl:variable name="vDayMonth" select=
"substring-before($vDate, concat('/',$vYear))"/>
<xsl:variable name="vMonth"
select="format-number(substring-before($vDayMonth, '/'), '00')"/>
<xsl:variable name="vDay"
select="format-number(substring-after($vDayMonth, '/'), '00')"/>
<xsl:attribute name="startdate">
<xsl:value-of select="concat($vYear,$vMonth,$vDay)"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="node()|@*" mode="pass2">
<xsl:copy>
<xsl:apply-templates mode="pass2" select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template mode="pass2" match="collection">
<xsl:copy>
<xsl:apply-templates mode="pass2" select="@*"/>
<xsl:apply-templates mode="pass2">
<xsl:sort select="@startdate"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<content date="1/13/2011 1:21:00 PM">
<collection vo="promotion">
<data vo="promotion" promotionid="64526" code="101P031" startdate="1/7/2011 12:00:00 AM"/>
<data vo="promotion" promotionid="64646" code="101P026" startdate="2/19/2011 12:00:00 AM"/>
<data vo="promotion" promotionid="64636" code="101P046" startdate="1/9/2011 12:00:00 AM"/>
</collection>
</content>
产生了想要的正确结果:
<content date="1/13/2011 1:21:00 PM">
<collection vo="promotion">
<data vo="promotion" promotionid="64526" code="101P031" startdate="20110107"/>
<data vo="promotion" promotionid="64636" code="101P046" startdate="20110109"/>
<data vo="promotion" promotionid="64646" code="101P026" startdate="20110219"/>
</collection>
</content>
请注意:
XSLT 1.0中的多通道转换需要使用特定于供应商的xxx:node-set()
函数将传递结果从其RTF(结果转换片段)类型转换为常规树(文件)。
此解决方案中使用的xxx:node-set()
函数是EXSLT的ext:node-set()
函数,它在大多数XSLT处理器上实现。