如何将复杂的XML转换为CSV?

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

How to convert complex Xml to csv?

问题

我正在用Java(初级阶段)编写程序,我真的需要在xslt转换方面帮助。需要从XML创建一个CSV文件。

我得到了这个xslt过滤器:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3. <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
  4. <xsl:template match="node()" name="conv">
  5. <xsl:call-template name="loop"/>
  6. </xsl:template>
  7. <xsl:template name="loop">
  8. <xsl:for-each select="./*[count(*) = 0]">
  9. <xsl:value-of select="."/>
  10. <xsl:if test="position() != last()">
  11. <xsl:text>,</xsl:text>
  12. </xsl:if>
  13. <xsl:if test="position() = last()">
  14. <xsl:text>,</xsl:text>
  15. </xsl:if>
  16. </xsl:for-each>
  17. <xsl:text>&#xA;</xsl:text>
  18. <xsl:for-each select="./*[(count(*) != 0) and (name()!='PARAMETRS')]">
  19. <xsl:call-template name="loop"/>
  20. </xsl:for-each>
  21. <xsl:text>&#xA;</xsl:text>
  22. </xsl:template>
  23. </xsl:stylesheet>

源XML:

  1. <Integration>
  2. <PARAMETRS>
  3. <ID>AZD</ID>
  4. <DATE>2020-01-01</DATE>
  5. </PARAMETRS>
  6. <ORG>
  7. <Thing>
  8. <object>10220</object>
  9. <type>U</type>
  10. <dyn>
  11. <items>
  12. <val>988009</val>
  13. <datebegin>2019-12-12</datebegin>
  14. </items>
  15. </dyn>
  16. </Thing>
  17. <Thing>
  18. <object>10221</object>
  19. <type>U</type>
  20. <dyn>
  21. <items>
  22. <val>988010</val>
  23. <datebegin>2019-12-13</datebegin>
  24. </items>
  25. <items>
  26. <val>988011</val>
  27. <datebegin>2019-12-14</datebegin>
  28. </items>
  29. </dyn>
  30. </Thing>
  31. </ORG>
  32. </Integration>

在输出中,我得到了逗号分隔的行,以及几行(相同的items)的值在下面。我无法弄清楚如何连接这些值...
我会通过使用value-of select = "concat"来实现,但是我的可能有多个dyn(1、2、3 ...),因此这不适用。
输出需要一个以逗号分隔的CSV。
请告知如何将项与其父项连接起来?或者是否有更简单的方法来解析具有不同数量子部分(子项)的XML?

预期输出:

  1. 10220,U,988009,2019-12-12
  2. 10221,U,988010,2019-12-13,988011,2019-12-14
英文:

I am writing a program in java( pre-junior), I really need help with xslt transformation. It is necessary to make a csv file from xml.
I got this xslt filter:

  1. &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  2. &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
  3. &lt;xsl:output method=&quot;text&quot; omit-xml-declaration=&quot;yes&quot; indent=&quot;no&quot;/&gt;
  4. &lt;xsl:template match=&quot;node()&quot; name=&quot;conv&quot;&gt;
  5. &lt;xsl:call-template name=&quot;loop&quot;/&gt;
  6. &lt;/xsl:template&gt;
  7. &lt;xsl:template name=&quot;loop&quot;&gt;
  8. &lt;xsl:for-each select=&quot;./*[count(*) = 0]&quot;&gt;
  9. &lt;xsl:value-of select=&quot;.&quot;/&gt;
  10. &lt;xsl:if test=&quot;position() != last()&quot;&gt;
  11. &lt;xsl:text&gt;,&lt;/xsl:text&gt;
  12. &lt;/xsl:if&gt;
  13. &lt;xsl:if test=&quot;position() = last()&quot;&gt;
  14. &lt;xsl:text&gt;,&lt;/xsl:text&gt;
  15. &lt;/xsl:if&gt;
  16. &lt;/xsl:for-each&gt;
  17. &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;
  18. &lt;xsl:for-each select=&quot;./*[(count(*) != 0) and (name()!=&#39;PARAMETRS&#39;)] &quot;&gt;
  19. &lt;xsl:call-template name=&quot;loop&quot;/&gt;
  20. &lt;/xsl:for-each&gt;
  21. &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;
  22. &lt;/xsl:template&gt;
  23. &lt;/xsl:stylesheet&gt;

Source xml:

  1. &lt;Integration&gt;
  2. &lt;PARAMETRS&gt;
  3. &lt;ID&gt;AZD&lt;/ID&gt;
  4. &lt;DATE&gt;2020-01-01&lt;/DATE&gt;
  5. &lt;/PARAMETRS&gt;
  6. &lt;ORG&gt;
  7. &lt;Thing&gt;
  8. &lt;object&gt;10220&lt;/object&gt;
  9. &lt;type&gt;U&lt;/type&gt;
  10. &lt;dyn&gt;
  11. &lt;items&gt;
  12. &lt;val&gt;988009&lt;/val&gt;
  13. &lt;datebegin&gt;2019-12-12&lt;/datebegin&gt;
  14. &lt;/items&gt;
  15. &lt;/dyn&gt;
  16. &lt;/Thing&gt;
  17. &lt;Thing&gt;
  18. &lt;object&gt;10221&lt;/object&gt;
  19. &lt;type&gt;U&lt;/type&gt;
  20. &lt;dyn&gt;
  21. &lt;items&gt;
  22. &lt;val&gt;988010&lt;/val&gt;
  23. &lt;datebegin&gt;2019-12-13&lt;/datebegin&gt;
  24. &lt;/items&gt;
  25. &lt;items&gt;
  26. &lt;val&gt;988011&lt;/val&gt;
  27. &lt;datebegin&gt;2019-12-14&lt;/datebegin&gt;
  28. &lt;/items&gt;
  29. &lt;/dyn&gt;
  30. &lt;/Thing&gt;
  31. &lt;/ORG&gt;
  32. &lt;/Integration&gt;

In the output, I get comma-separated lines, and a few more lines (those same items) with the values below. and can't figure out how to concatenate the values ...
I would do it via value-of select = "concat" but my <items> may have several dyn (1, 2, 3 ...), hence this is not suitable.
The output needs a csv separated by commas.
Please advise how to concatenate the item with its parent? Or there are simpler ways to parse xml with a different number of subsections(childs).

Expected output:

  1. 10220,U,988009,2019-12-12
  2. 10221,U,988010,2019-12-13,988011,2019-12-14

答案1

得分: 0

以下是翻译好的内容:

XSLT 1.0

  1. <xsl:stylesheet version="1.0"
  2. xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3. <xsl:output method="text"/>
  4. <xsl:template match="/Integration">
  5. <xsl:for-each select="ORG/Thing">
  6. <xsl:value-of select="object"/>
  7. <xsl:text>,</xsl:text>
  8. <xsl:value-of select="type"/>
  9. <xsl:text>,</xsl:text>
  10. <xsl:for-each select="dyn/items">
  11. <xsl:value-of select="val"/>
  12. <xsl:text>,</xsl:text>
  13. <xsl:value-of select="datebegin"/>
  14. <xsl:if test="position() != last()">
  15. <xsl:text>,</xsl:text>
  16. </xsl:if>
  17. </xsl:for-each>
  18. <xsl:text>&#xA;</xsl:text>
  19. </xsl:for-each>
  20. </xsl:template>
  21. </xsl:stylesheet>

请注意,输出中每个 items 都有一组列;这不是理想的CSV结构。

英文:

The output you show can be easily obtained using the following stylesheet:

XSLT 1.0

  1. &lt;xsl:stylesheet version=&quot;1.0&quot;
  2. xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
  3. &lt;xsl:output method=&quot;text&quot;/&gt;
  4. &lt;xsl:template match=&quot;/Integration&quot;&gt;
  5. &lt;xsl:for-each select=&quot;ORG/Thing&quot;&gt;
  6. &lt;xsl:value-of select=&quot;object&quot;/&gt;
  7. &lt;xsl:text&gt;,&lt;/xsl:text&gt;
  8. &lt;xsl:value-of select=&quot;type&quot;/&gt;
  9. &lt;xsl:text&gt;,&lt;/xsl:text&gt;
  10. &lt;xsl:for-each select=&quot;dyn/items&quot;&gt;
  11. &lt;xsl:value-of select=&quot;val&quot;/&gt;
  12. &lt;xsl:text&gt;,&lt;/xsl:text&gt;
  13. &lt;xsl:value-of select=&quot;datebegin&quot;/&gt;
  14. &lt;xsl:if test=&quot;position() != last()&quot;&gt;
  15. &lt;xsl:text&gt;,&lt;/xsl:text&gt;
  16. &lt;/xsl:if&gt;
  17. &lt;/xsl:for-each&gt;
  18. &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;
  19. &lt;/xsl:for-each&gt;
  20. &lt;/xsl:template&gt;
  21. &lt;/xsl:stylesheet&gt;

Note that the output has a set of columns for each items; this is not an ideal CSV structure.

答案2

得分: 0

如果您能使用XSLT 2.0,它将带来新的强大功能。

Oracle XML Developer Kit(XDK)支持XSLT 2.0

这是链接:使用Java的XSLT处理器

下面的方法执行以下操作:

  • 使用string-join()函数通过.//*/(text()[1]表达式在不同层次结构级别上连接所有子元素值。
  • xs:token强制转换删除空格。
  • XPath谓词[. != &#39;&#39;]删除空序列成员。

XSLT 2.0

  1. <?xml version='1.0'?>
  2. <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  3. <xsl:output method="text"/>
  4. <xsl:template match="/Integration">
  5. <xsl:for-each select="ORG/Thing">
  6. <xsl:value-of select="string-join((.//*/(text()[1] cast as xs:token?))[. != &#39;&#39;],',')"/>
  7. <xsl:text>&#xA;</xsl:text>
  8. </xsl:for-each>
  9. </xsl:template>
  10. </xsl:stylesheet>

输出

  1. 10220,U,988009,2019-12-12
  2. 10221,U,988010,2019-12-13,988011,2019-12-14

根据Marting Honnen的绝妙提示,这里是更简洁的XSLT 2.0版本,不需要任何循环。

XSLT 2.0

  1. <?xml version="1.0"?>
  2. <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  3. <xsl:output method="text"/>
  4. <xsl:template match="/Integration">
  5. <xsl:value-of select="ORG/Thing/string-join((.//*/(text()[1] cast as xs:token?))[. != &#39;&#39;],',')" separator="&#xA;"/>
  6. </xsl:template>
  7. </xsl:stylesheet>
英文:

If you can use XSLT 2.0, it opens up new powerful functionality.

Oracle XML Developer Kit (XDK) supports XSLT 2.0

Here is the link: Using the XSLT Processor for Java

The approach below is doing the following:

  • Using string-join() function to concatenate all child elements values
    on a different hierarchy level via .//*/(text()[1] expression.
  • xs:token casting removes white spaces.
  • XPath predicate [. != &#39;&#39;] removes empty sequence members.

XSLT 2.0

  1. &lt;?xml version=&#39;1.0&#39;?&gt;
  2. &lt;xsl:stylesheet version=&quot;2.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
  3. &lt;xsl:output method=&quot;text&quot;/&gt;
  4. &lt;xsl:template match=&quot;/Integration&quot;&gt;
  5. &lt;xsl:for-each select=&quot;ORG/Thing&quot;&gt;
  6. &lt;xsl:value-of select=&quot;string-join((.//*/(text()[1] cast as xs:token?))[. != &#39;&#39;],&#39;,&#39;)&quot;/&gt;
  7. &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt;
  8. &lt;/xsl:for-each&gt;
  9. &lt;/xsl:template&gt;
  10. &lt;/xsl:stylesheet&gt;

> Output

  1. 10220,U,988009,2019-12-12
  2. 10221,U,988010,2019-12-13,988011,2019-12-14

Based on the Marting Honnen great tip, here is even more concise XSLT 2.0 version without any loop.

XSLT 2.0

  1. &lt;?xml version=&quot;1.0&quot;?&gt;
  2. &lt;xsl:stylesheet version=&quot;2.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
  3. &lt;xsl:output method=&quot;text&quot;/&gt;
  4. &lt;xsl:template match=&quot;/Integration&quot;&gt;
  5. &lt;xsl:value-of select=&quot;ORG/Thing/string-join((.//*/(text()[1] cast as xs:token?))[. != &#39;&#39;],&#39;,&#39;)&quot; separator=&quot;&amp;#xA;&quot;/&gt;
  6. &lt;/xsl:template&gt;
  7. &lt;/xsl:stylesheet&gt;

huangapple
  • 本文由 发表于 2020年8月20日 01:53:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/63492468.html
匿名

发表评论

匿名网友

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

确定