简体   繁体   English

基于可选标签的 XML 拆分

[英]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:这将为每一个创建一个新组:

  • a tag1 element;一个tag1元素;
  • a tag2 element that does not immediately follow a tag1 element;一个tag2不紧跟一个元素tag1元;
  • a tag3 element that does not immediately follow a tag2 or a tag1 element.一个tag3不紧跟一个元素tag2tag1元。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM