用深层XML结构转换成CSV

huangapple go评论52阅读模式
英文:

Groovy XML to CSV with deep XML structure

问题

我需要一个Groovy脚本,将XML结构转换为CSV文件,不包括头部行。

XML的结构如下:

<stock>
    <field1>Header</field1>
    <field2>H1</field2>
    <positions>
        <data1>Hello</data1>
        <data2>P1</data2>
    </positions>
    <positions>
        <data1>World</data1>
        <data2>P2</data2>
    </positions>
</stock>
<stock>
    <field1>Header</field1>
    <field2>H2</field2>
    <positions>
        <data1>Hello</data1>
        <data2>P3</data2>
    </positions>
    <positions>
        <data1>World</data1>
        <data2>P4</data2>
    </positions>
</stock>

你尝试的代码似乎没有达到你的需求。CSV应该如下所示:

Header|H1
Hello|P1
World|P2
Header|H2
Hello|P3
World|P4

欢迎任何帮助。谢谢。

英文:

I need a groovy script that is transforming a XML structure into a CSV File without a header line.

XML lookes like this:

	&lt;stock&gt;
	        &lt;field1&gt;Header&lt;/field1&gt;
                &lt;field2&gt;H1&lt;/field2&gt;
		&lt;positions&gt;
	          &lt;data1&gt;Hello&lt;/data1&gt;
	          &lt;data2&gt;P1&lt;/data2&gt;
		&lt;/positions&gt;
		&lt;positions&gt;
	          &lt;data1&gt;World&lt;/data1&gt;
	          &lt;data2&gt;P2&lt;/data2&gt;
		&lt;/positions&gt;
	&lt;/stock&gt;
	&lt;stock&gt;
	        &lt;field1&gt;Header&lt;/field1&gt;
                &lt;field2&gt;H2&lt;/field2&gt;
		&lt;positions&gt;
	          &lt;data1&gt;Hello&lt;/data1&gt;
	          &lt;data2&gt;P3&lt;/data2&gt;
		&lt;/positions&gt;
		&lt;positions&gt;
	          &lt;data1&gt;World&lt;/data1&gt;
	          &lt;data2&gt;P4&lt;/data2&gt;
		&lt;/positions&gt;
	&lt;/stock&gt;

I tried this but it is not doing what i need to have.

		//parse input
		def parsedXml = new XmlParser().parseText(ins)
		
		def content = new XmlSlurper().parseText(ins)
		def csv = content.stock.positions.inject(header){ result, row -&gt;
		 [result, row.children().collect().join(&#39;|&#39;)].join(&quot;\n&quot;)

CSV should look like this

Header|H1
Hello|P1
World|P2
Header|H2
Hello|P3
World|P4

any help is appreciated. thanks

答案1

得分: 0

这不是特别高效,因为它将所有内容读入内存,但这会起作用:

String xmlString = "&lt;stocks&gt;&lt;stock&gt; &lt;field1&gt;Header&lt;/field1&gt; &lt;field2&gt;H1&lt;/field2&gt; &lt;positions&gt; &lt;data1&gt;Hello&lt;/data1&gt; &lt;data2&gt;P1&lt;/data2&gt; &lt;/positions&gt; &lt;positions&gt; &lt;data1&gt;World&lt;/data1&gt; &lt;data2&gt;P2&lt;/data2&gt; &lt;/positions&gt; &lt;/stock&gt; &lt;stock&gt; &lt;field1&gt;Header&lt;/field1&gt; &lt;field2&gt;H2&lt;/field2&gt; &lt;positions&gt; &lt;data1&gt;Hello&lt;/data1&gt; &lt;data2&gt;P3&lt;/data2&gt; &lt;/positions&gt; &lt;positions&gt; &lt;data1&gt;World&lt;/data1&gt; &lt;data2&gt;P4&lt;/data2&gt; &lt;/positions&gt; &lt;/stock&gt;&lt;/stocks&gt;";
def xml = new XmlSlurper().parseText( xmlString )
List&lt;List&lt;String&gt;&gt; output = []
xml.stock.each { stock -&gt;
   output &lt;&lt; [stock.field1.text(),stock.field2.text()]
   stock.positions.each { position -&gt;
      output &lt;&lt; [ position.data1.text(), position.data2.text() ]
   }
}
println( output.collect { it.join("|") }.join("\n") )
英文:

It's not super efficient because it reads everything into memory, but this will work:

String ​xmlString = &quot;&quot;&quot;&lt;stocks&gt;&lt;stock&gt;             &lt;field1&gt;Header&lt;/field1&gt;                 &lt;field2&gt;H1&lt;/field2&gt;         &lt;positions&gt;               &lt;data1&gt;Hello&lt;/data1&gt;               &lt;data2&gt;P1&lt;/data2&gt;         &lt;/positions&gt;         &lt;positions&gt;               &lt;data1&gt;World&lt;/data1&gt;               &lt;data2&gt;P2&lt;/data2&gt;         &lt;/positions&gt;     &lt;/stock&gt;     &lt;stock&gt;             &lt;field1&gt;Header&lt;/field1&gt;                 &lt;field2&gt;H2&lt;/field2&gt;         &lt;positions&gt;               &lt;data1&gt;Hello&lt;/data1&gt;               &lt;data2&gt;P3&lt;/data2&gt;         &lt;/positions&gt;         &lt;positions&gt;               &lt;data1&gt;World&lt;/data1&gt;               &lt;data2&gt;P4&lt;/data2&gt;         &lt;/positions&gt;     &lt;/stock&gt;​&lt;/stocks&gt;&quot;&quot;&quot;​​​
def xml = new ​XmlSlurper​().parseText( xmlString )

List&lt;List&lt;String&gt;&gt; output = []
xml.stock.each { stock -&gt;
   output &lt;&lt; [stock.field1.text(),stock.field2.text()]
   stock.positions.each { position -&gt;
      output &lt;&lt; [ position.data1.text(), position.data2.text() ]
   }
}
println( output.collect { it.join(&quot;|&quot;) }.join(&quot;\n&quot;) )

答案2

得分: 0

以下是代码的中文翻译:

你可以遍历XML树并收集具有匹配名称的节点

def ins = '''
<root>
    <stock>
        <field1>Header</field1>
        <field2>H1</field2>
        <positions>
            <data1>Hello</data1>
            <data2>P1</data2>
        </positions>
        <positions>
            <data1>World</data1>
            <data2>P2</data2>
        </positions>
    </stock>
    <stock>
        <field1>Header</field1>
        <field2>H2</field2>
        <positions>
            <data1>Hello</data1>
            <data2>P3</data2>
        </positions>
        <positions>
            <data1>World</data1>
            <data2>P4</data2>
        </positions>
    </stock>
</root>
'''
def content = new XmlSlurper().parseText(ins)

def csv = content.depthFirst()
    .findAll { it.name().matches(/(field|data).*/) }
    .collect{ it.text() }.collate(2)
    .collect { it.join("|") }.join("\n")

或者,如果你需要一种相对通用的方法,可以扩展字段和数据标签的数量:

def csv = content.depthFirst()
    .findAll { it.name() in ["stock", "positions"] }
    .collect { node -> node.children()
                .findAll{ it.name() != "positions" }
                .collect{ it.text() } }
    .collect { it.join("|") }.join("\n")

注意:这些是给定代码片段的中文翻译,不包括代码的执行或其他信息。

英文:

You could traverse the xml-tree and collect the nodes with matching names:

def ins = &#39;&#39;&#39;
&lt;root&gt;
	&lt;stock&gt;
		&lt;field1&gt;Header&lt;/field1&gt;
		&lt;field2&gt;H1&lt;/field2&gt;
		&lt;positions&gt;
			&lt;data1&gt;Hello&lt;/data1&gt;
			&lt;data2&gt;P1&lt;/data2&gt;
		&lt;/positions&gt;
		&lt;positions&gt;
			&lt;data1&gt;World&lt;/data1&gt;
			&lt;data2&gt;P2&lt;/data2&gt;
		&lt;/positions&gt;
	&lt;/stock&gt;
	&lt;stock&gt;
		&lt;field1&gt;Header&lt;/field1&gt;
		&lt;field2&gt;H2&lt;/field2&gt;
		&lt;positions&gt;
			&lt;data1&gt;Hello&lt;/data1&gt;
			&lt;data2&gt;P3&lt;/data2&gt;
		&lt;/positions&gt;
		&lt;positions&gt;
			&lt;data1&gt;World&lt;/data1&gt;
			&lt;data2&gt;P4&lt;/data2&gt;
		&lt;/positions&gt;
	&lt;/stock&gt;
&lt;/root&gt;
&#39;&#39;&#39;
def content = new XmlSlurper().parseText(ins)

def csv = content.depthFirst()
        .findAll { it.name().matches(/(field|data).*/) }
        .collect{ it.text() }.collate(2)
        .collect { it.join(&quot;|&quot;) }.join(&quot;\n&quot;)

Or if you need a somewhat generic approach where you can extend the number of field and data tags:

def csv = content.depthFirst()
        .findAll { it.name() in [&quot;stock&quot;, &quot;positions&quot;] }
        .collect { node -&gt; node.children()
                    .findAll{ it.name() != &quot;positions&quot; }
                    .collect{ it.text() } }
        .collect { it.join(&quot;|&quot;) }.join(&quot;\n&quot;)

huangapple
  • 本文由 发表于 2023年3月20日 22:38:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75791669.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定