xml - XSLT - 如何在新父节点中对一组递归节点进行分组
问题描述
我开始使用 XSLT,在探索了一些解决方案之后,我认为与您分享我的问题是个好主意。也许有人可以帮助我。
我有一个这样的 XML 输入数据:
<?xml version="1.0" encoding="windows-1252"?>
<DOCUMENT>
<SSDP>
<DP>A</DP>
<DX>B</DX>
<XN>1</XN>
<PP>2</PP>
<CO>3</CO>
<XN>4</XN>
<PP>5</PP>
<XN>6</XN>
<PP>7</PP>
<CO>8</CO>
</SSDP>
<SSDP>
<DP>A</DP>
<DL>B</DL>
<DX>C</DX>
<XN>1</XN>
<PP>2</PP>
<CO>3</CO>
<XN>4</XN>
<PP>5</PP>
</SSDP>
</DOCUMENT>
如您所见,有一组递归节点。具体来说,每个“XN”节点开始一组新的递归节点,直到下一个“XN”字段。(“XN”节点之间的字段数可以是动态的,如您在输入 XML 示例中所见)。挑战是在新节点“DATA”中包含每组递归节点。
想要的输出如下:
<?xml version="1.0" encoding="windows-1252"?>
<DOCUMENT>
<SSDP>
<DP>A</DP>
<DX>B</DX>
<DATA>
<XN>1</XN>
<PP>2</PP>
<CO>3</CO>
</DATA>
<DATA>
<XN>4</XN>
<PP>5</PP>
</DATA>
<DATA>
<XN>6</XN>
<PP>7</PP>
<CO>8</CO>
</DATA>
</SSDP>
<SSDP>
<DP>A</DP>
<DL>B</DL>
<DX>C</DX>
<DATA>
<XN>1</XN>
<PP>2</PP>
<CO>3</CO>
</DATA>
<DATA>
<XN>4</XN>
<PP>5</PP>
</DATA>
</SSDP>
</DOCUMENT>
正如我之前所说,我是 XSLT 的初学者,我试图创建一个来解决这个问题,但恐怕我还没有足够的知识。
我的第一个 XSLT 版本如下:
<?xml version="1.0" encoding="windows-1252"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="DOCUMENT">
<DOCUMENT>
<xsl:for-each select="SSDP">
<SSDP>
<xsl:for-each select="*">
<!-- First element that define a DATA node -->
<xsl:if test="name(.)='XN'">
<xsl:element name="DATA">
<xsl:copy-of select="."/>
</xsl:element>
</xsl:if>
<!-- List of elements that define a DATA node -->
<xsl:if test="name(.)!='XN' and
name(.)!='PP' and
name(.)!='CO'">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</SSDP>
</xsl:for-each>
</DOCUMENT>
</xsl:template>
</xsl:stylesheet>
但结果是不完整的...
<?xml version="1.0" encoding="UTF-8"?>
<DOCUMENT>
<SSDP>
<DP>A</DP>
<DX>B</DX>
<DATA>
<XN>1</XN>
</DATA>
<DATA>
<XN>4</XN>
</DATA>
<DATA>
<XN>6</XN>
</DATA>
</SSDP>
<SSDP>
<DP>A</DP>
<DL>B</DL>
<DX>C</DX>
<DATA>
<XN>1</XN>
</DATA>
<DATA>
<XN>4</XN>
</DATA>
</SSDP>
</DOCUMENT>
我认为在包含“DATA”节点并将鼠标悬停在“XN”节点上之后,我需要添加以下“PP”或“CO”节点,使用“following::”或类似的功能......但我没有不知道怎么做。
另外,我担心有比我想象的更好的方法来解决这个问题。
提前致谢!
解决方案
另外,我担心有比我想象的更好的方法来解决这个问题。
我相信有:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/DOCUMENT">
<xsl:copy>
<xsl:for-each select="SSDP">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="XN">
<xsl:choose>
<xsl:when test="self::XN">
<DATA>
<xsl:copy-of select="current-group()" />
</DATA>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
推荐阅读
- php - 如何在 laravel 5.4 中运行 .dll 文件
- openmdao - 组件 IO 是否有额外的内存限制
- mysql - 使用命令提示符安装 mysql 时出现问题,对于 django
- zurb-foundation - 在 Mac 上安装 Foundation-cli 的问题
- sql - 在 oracle 中快速执行什么语句,删除+插入或插入 ID 不在列表中。?
- apache-kafka-streams - 合并两个时间窗口的最佳模式是什么
- python - Matplotlib:从二进制数据填充
- html - 如何显示位置在通过 XMLHttpRequest 访问的 JSON 文件中的图像?
- java - Java Map computeIfAbsent 问题
- laravel - 如何在 Laravel 中直接访问数组或对象?