XML 根据可选标签拆分
XML split based on optional tags
我正在寻找基于标签的 xml 文件的简单拆分;假设 3 个标签(可选)总是重复并且需要拆分,如下所示:
输入
<?xml version="1.0" encoding="UTF-8"?>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
<tag1>1</tag1>
<tag2>2</tag2>
<tag3>3</tag3>
<tag1>apple</tag1>
<tag2>orange</tag2>
<tag3>mango</tag3>
</Test>
预期输出
<Root>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
</Test>
<Test>
<tag1>1</tag1>
<tag2>2</tag2>
<tag3>3</tag3>
</Test>
<Test>
<tag1>apple</tag1>
<tag2>orange</tag2>
<tag3>mango</tag3>
</Test>
</Root>
这里的挑战是所有 3 个标签都是可选的,并且可以或不能出现在一个块中。如果没有可选 - 我的问题已经在这里得到回答 -
感谢任何帮助
谢谢
如果我理解正确,你想做的是:
XSLT 1.0
<xsl:stylesheet version="1.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="/Test">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
<xsl:template match="tag1">
<Test>
<xsl:copy-of select=". | following-sibling::*[1][self::tag2 or self::tag3]"/>
<xsl:if test="following-sibling::*[1][self::tag2]">
<xsl:copy-of select="following-sibling::*[2][self::tag3] "/>
</xsl:if>
</Test>
</xsl:template>
<xsl:template match="tag2[not(preceding-sibling::*[1][self::tag1])]">
<Test>
<xsl:copy-of select=". | following-sibling::*[1][self::tag3]"/>
</Test>
</xsl:template>
<xsl:template match="tag3[not(preceding-sibling::*[1][self::tag2 or self::tag1])]">
<Test>
<xsl:copy-of select="."/>
</Test>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
这将为以下各项创建一个新组:
- 一个
tag1
元素;
tag2
元素没有紧跟在 tag1
元素之后;
tag3
元素没有紧跟在 tag2
或 tag1
元素之后。
组以 tag3
或序列中断前的最后一个元素结束,以先到者为准。
应用于以下测试输入:
XML
<Test>
<tag2>B</tag2>
<tag3>C</tag3>
<tag1>1</tag1>
<tag3>3</tag3>
<tag1>apple</tag1>
<tag2>orange</tag2>
<tag1>A</tag1>
<tag2>B</tag2>
<tag1>1</tag1>
<tag3>3</tag3>
<tag3>mango</tag3>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
</Test>
结果将是:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Test>
<tag2>B</tag2>
<tag3>C</tag3>
</Test>
<Test>
<tag1>1</tag1>
<tag3>3</tag3>
</Test>
<Test>
<tag1>apple</tag1>
<tag2>orange</tag2>
</Test>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
</Test>
<Test>
<tag1>1</tag1>
<tag3>3</tag3>
</Test>
<Test>
<tag3>mango</tag3>
</Test>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
</Test>
</Root>
这是一种替代解决方案,适用于任何规模的组,前提是组中至少有一个元素始终存在。
在此示例中,每个组中最多有 5 个元素,元素 tag3
将出现在每个组中:
XML
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
<tag4>D</tag4>
<tag5>E</tag5>
<tag2>2</tag2>
<tag3>3</tag3>
<tag5>5</tag5>
<tag3>C</tag3>
<tag3>3</tag3>
<tag4>4</tag4>
<tag5>5</tag5>
<tag2>B</tag2>
<tag3>C</tag3>
<tag4>D</tag4>
<tag1>1</tag1>
<tag3>3</tag3>
<tag5>5</tag5>
</Test>
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="elems-before" match="tag1 | tag2" use="generate-id(following-sibling::tag3[1])" />
<xsl:key name="elems-after" match="tag4 | tag5" use="generate-id(preceding-sibling::tag3[1])" />
<xsl:template match="/Test">
<Root>
<xsl:for-each select="tag3">
<Test>
<xsl:copy-of select="key('elems-before', generate-id())"/>
<xsl:copy-of select="."/>
<xsl:copy-of select="key('elems-after', generate-id())"/>
</Test>
</xsl:for-each>
</Root>
</xsl:template>
</xsl:stylesheet>
结果
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
<tag4>D</tag4>
<tag5>E</tag5>
</Test>
<Test>
<tag2>2</tag2>
<tag3>3</tag3>
<tag5>5</tag5>
</Test>
<Test>
<tag3>C</tag3>
</Test>
<Test>
<tag3>3</tag3>
<tag4>4</tag4>
<tag5>5</tag5>
</Test>
<Test>
<tag2>B</tag2>
<tag3>C</tag3>
<tag4>D</tag4>
</Test>
<Test>
<tag1>1</tag1>
<tag3>3</tag3>
<tag5>5</tag5>
</Test>
</Root>
我正在寻找基于标签的 xml 文件的简单拆分;假设 3 个标签(可选)总是重复并且需要拆分,如下所示:
输入
<?xml version="1.0" encoding="UTF-8"?>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
<tag1>1</tag1>
<tag2>2</tag2>
<tag3>3</tag3>
<tag1>apple</tag1>
<tag2>orange</tag2>
<tag3>mango</tag3>
</Test>
预期输出
<Root>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
</Test>
<Test>
<tag1>1</tag1>
<tag2>2</tag2>
<tag3>3</tag3>
</Test>
<Test>
<tag1>apple</tag1>
<tag2>orange</tag2>
<tag3>mango</tag3>
</Test>
</Root>
这里的挑战是所有 3 个标签都是可选的,并且可以或不能出现在一个块中。如果没有可选 - 我的问题已经在这里得到回答 -
感谢任何帮助
谢谢
如果我理解正确,你想做的是:
XSLT 1.0
<xsl:stylesheet version="1.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="/Test">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
<xsl:template match="tag1">
<Test>
<xsl:copy-of select=". | following-sibling::*[1][self::tag2 or self::tag3]"/>
<xsl:if test="following-sibling::*[1][self::tag2]">
<xsl:copy-of select="following-sibling::*[2][self::tag3] "/>
</xsl:if>
</Test>
</xsl:template>
<xsl:template match="tag2[not(preceding-sibling::*[1][self::tag1])]">
<Test>
<xsl:copy-of select=". | following-sibling::*[1][self::tag3]"/>
</Test>
</xsl:template>
<xsl:template match="tag3[not(preceding-sibling::*[1][self::tag2 or self::tag1])]">
<Test>
<xsl:copy-of select="."/>
</Test>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
这将为以下各项创建一个新组:
- 一个
tag1
元素; tag2
元素没有紧跟在tag1
元素之后;tag3
元素没有紧跟在tag2
或tag1
元素之后。
组以 tag3
或序列中断前的最后一个元素结束,以先到者为准。
应用于以下测试输入:
XML
<Test>
<tag2>B</tag2>
<tag3>C</tag3>
<tag1>1</tag1>
<tag3>3</tag3>
<tag1>apple</tag1>
<tag2>orange</tag2>
<tag1>A</tag1>
<tag2>B</tag2>
<tag1>1</tag1>
<tag3>3</tag3>
<tag3>mango</tag3>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
</Test>
结果将是:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Test>
<tag2>B</tag2>
<tag3>C</tag3>
</Test>
<Test>
<tag1>1</tag1>
<tag3>3</tag3>
</Test>
<Test>
<tag1>apple</tag1>
<tag2>orange</tag2>
</Test>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
</Test>
<Test>
<tag1>1</tag1>
<tag3>3</tag3>
</Test>
<Test>
<tag3>mango</tag3>
</Test>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
</Test>
</Root>
这是一种替代解决方案,适用于任何规模的组,前提是组中至少有一个元素始终存在。
在此示例中,每个组中最多有 5 个元素,元素 tag3
将出现在每个组中:
XML
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
<tag4>D</tag4>
<tag5>E</tag5>
<tag2>2</tag2>
<tag3>3</tag3>
<tag5>5</tag5>
<tag3>C</tag3>
<tag3>3</tag3>
<tag4>4</tag4>
<tag5>5</tag5>
<tag2>B</tag2>
<tag3>C</tag3>
<tag4>D</tag4>
<tag1>1</tag1>
<tag3>3</tag3>
<tag5>5</tag5>
</Test>
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="elems-before" match="tag1 | tag2" use="generate-id(following-sibling::tag3[1])" />
<xsl:key name="elems-after" match="tag4 | tag5" use="generate-id(preceding-sibling::tag3[1])" />
<xsl:template match="/Test">
<Root>
<xsl:for-each select="tag3">
<Test>
<xsl:copy-of select="key('elems-before', generate-id())"/>
<xsl:copy-of select="."/>
<xsl:copy-of select="key('elems-after', generate-id())"/>
</Test>
</xsl:for-each>
</Root>
</xsl:template>
</xsl:stylesheet>
结果
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Test>
<tag1>A</tag1>
<tag2>B</tag2>
<tag3>C</tag3>
<tag4>D</tag4>
<tag5>E</tag5>
</Test>
<Test>
<tag2>2</tag2>
<tag3>3</tag3>
<tag5>5</tag5>
</Test>
<Test>
<tag3>C</tag3>
</Test>
<Test>
<tag3>3</tag3>
<tag4>4</tag4>
<tag5>5</tag5>
</Test>
<Test>
<tag2>B</tag2>
<tag3>C</tag3>
<tag4>D</tag4>
</Test>
<Test>
<tag1>1</tag1>
<tag3>3</tag3>
<tag5>5</tag5>
</Test>
</Root>