xml - XSLT:使用输入 XML 中的唯一且已排序的日期创建新的 XML 节点
问题描述
我已经为此搜索了其他各种帖子,但到目前为止还没有能够使其正常工作。我需要在生成的 XML 中添加一个新节点,该节点应该包含输入 XML 中的所有“start_date”节点。结果节点应具有按升序排序的唯一日期。这是我的 XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<record>
<id>378</id>
<A>
<Field1>378</Field1>
<AX>
<Field1>x</Field1>
<Field2>xx</Field2>
</AX>
<AY>
<Field1>yy</Field1>
</AY>
<B>
<end_date>9999-12-31</end_date>
<start_date>2019-03-27</start_date>
</B>
<B>
<end_date>9999-12-31</end_date>
<start_date>2019-03-27</start_date>
</B>
<C>
<start_date>2012-02-01</start_date>
<user_id>10005557</user_id>
<D>
<end_date>9999-12-31</end_date>
<start_date>2021-06-30</start_date>
</D>
</C>
</A>
</record>
<record>
<id>379</id>
<A>
<Field1>300</Field1>
<AX>
<Field1>x</Field1>
<Field2>xx</Field2>
</AX>
<AY>
<Field1>yy</Field1>
</AY>
<B>
<end_date>9999-12-31</end_date>
<start_date>2019-03-27</start_date>
</B>
<C>
<start_date>2012-02-01</start_date>
<user_id>10005557</user_id>
<D>
<end_date>9999-12-31</end_date>
<start_date>2021-06-30</start_date>
</D>
</C>
</A>
</record>
</root>
这是我的 XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<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 method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<root>
<xsl:for-each select="//record">
<record>
<xsl:copy-of select="./*"/>
<xsl:variable name="i" select="position()"/>
<StartDates>
<xsl:copy-of select="//child::record[$i]/descendant::start_date"/>
</StartDates>
</record>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template match="StartDates">
<xsl:variable name="nDate" select="replace(//start_date,'-','')"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="$nDate">
<xsl:sort select="$nDate"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
第一个模板是收集所有日期。在第二个模板中,我试图对这些日期进行排序。谁能帮我排序和选择独特的日期。
这是预期的输出:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<record>
<id>378</id>
<A>
<Field1>378</Field1>
<AX>
<Field1>x</Field1>
<Field2>xx</Field2>
</AX>
<AY>
<Field1>yy</Field1>
</AY>
<B>
<end_date>9999-12-31</end_date>
<start_date>2019-03-27</start_date>
</B>
<B>
<end_date>9999-12-31</end_date>
<start_date>2019-03-27</start_date>
</B>
<C>
<start_date>2012-02-01</start_date>
<user_id>10005557</user_id>
<D>
<end_date>9999-12-31</end_date>
<start_date>2021-06-30</start_date>
</D>
</C>
</A>
<StartDates>
<start_date>2012-02-01</start_date>
<start_date>2019-03-27</start_date>
<start_date>2021-06-30</start_date>
</StartDates>
</record>
<record>
<id>379</id>
<A>
<Field1>300</Field1>
<AX>
<Field1>x</Field1>
<Field2>xx</Field2>
</AX>
<AY>
<Field1>yy</Field1>
</AY>
<B>
<end_date>9999-12-31</end_date>
<start_date>2019-03-27</start_date>
</B>
<C>
<start_date>2012-02-01</start_date>
<user_id>10005557</user_id>
<D>
<end_date>9999-12-31</end_date>
<start_date>2021-06-30</start_date>
</D>
</C>
</A>
<StartDates>
<start_date>2012-02-01</start_date>
<start_date>2019-03-27</start_date>
<start_date>2021-06-30</start_date>
</StartDates>
</record>
</root>
任何帮助表示赞赏谢谢!
解决方案
写一个模板
<xsl:template match="record">
<xsl:copy>
<xsl:apply-templates/>
<StartDates>
<xsl:for-each-group select=".//start_date" group-by=".">
<xsl:sort select="."/>
<xsl:copy-of select="."/>
</xsl:for-each-group>
</StartDates>
</xsl:copy>
</xsl:template>
通过恒等转换处理其余部分(即声明<xsl:mode on-no-match="shallow-copy"/>
或说明 XSLT 2 的恒等转换模板:
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
)。
推荐阅读
- javascript - 我的下拉按钮在文本上不可点击,但可在按钮上的其他任何地方点击
- javascript - Promises:如何返回具有其他错误处理程序的 Promise
- jsonschema - json-schema 具有类型 x 的附加属性和至少一个
- r - 在控制台与 R 降价单元中运行时调度不同的打印方法?
- exchange-server - 如何创建基于域的 Exchange 2013/16 邮件流规则
- msix - 如何从命令行构建 MSIX
- laravel - 如何向具有不同会员角色的会员发送通知?
- asp.net-core-mvc - 如何在 vs2019 MVC Core 3.1 的包管理器控制台中搭建控制器?
- sql - Hive 中的转置数组
- sql - SQL:添加缺失的日期和值