[英]XML split based on optional tags
I am looking for a simple split of an xml file just based on tags;我正在寻找仅基于标签的 xml 文件的简单拆分; say 3 tags (optional) always repeat and need split as depicted below:
说 3 个标签(可选)总是重复并且需要拆分,如下所示:
Input输入
<?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>
Expected Output预期产出
<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>
The challenge here is that all 3 tags are optional and can or cannot appear in a block.这里的挑战是所有 3 个标签都是可选的,可以或不能出现在一个块中。 If there weren't optional - my question was already answered here - Split based on just tags
如果没有可选 - 我的问题已经在这里回答 - 基于标签拆分
Any help is appreciated任何帮助表示赞赏
Thanks谢谢
If I understand the requirement correctly, you want to do:如果我正确理解了要求,您想要执行以下操作:
XSLT 1.0 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>
This will start a new group for each of these:这将为每一个创建一个新组:
tag1
element;tag1
元素;tag2
element that does not immediately follow a tag1
element;tag2
不紧跟一个元素tag1
元;tag3
element that does not immediately follow a tag2
or a tag1
element.tag3
不紧跟一个元素tag2
或tag1
元。 A group ends with tag3
, or with the last element before the sequence breaks, whichever comes first.组以
tag3
结束,或以序列中断前的最后一个元素结束,以先到者为准。
Applied to the following test input:应用于以下测试输入:
XML 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>
the result will be:结果将是:
<?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>
Here's an alternative solution that can work with groups of any size, provided that at least one element of the group will always be present.这是一种替代解决方案,可以与任何规模的组一起使用,前提是该组中至少有一个元素始终存在。
In this example there are up to 5 elements in each group, and element tag3
will be present in each group:在这个例子中,每组最多有 5 个元素,每组中将出现元素
tag3
:
XML 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 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>
Result结果
<?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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.