XSLT - 如何在新的父节点中对一组递归节点进行分组
XSLT - How grouping a set of recursive nodes within a new parent node
我开始使用 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::”之类的函数。 ..但我不知道如何。
另外,恐怕有比我想象的更好的方法来解决这个问题。
提前致谢!
Also I'm afraid that there is a much better way to resolve this issue than I'm thinking.
我相信有:
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>
我开始使用 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::”之类的函数。 ..但我不知道如何。
另外,恐怕有比我想象的更好的方法来解决这个问题。
提前致谢!
Also I'm afraid that there is a much better way to resolve this issue than I'm thinking.
我相信有:
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>