2012-12-30 69 views
5

我有一个XML文件,我需要将它转换为XQuery。考虑一个简单的组XML的:使用XQuery从XML到CSV的转换

books[book] 
book[@isbn, title, descrption] 

如:

<books> 
    <book isbn="1590593049"> 
     <title>Extending Flash MX 2004</title> 
     <description> 
     Using javascript alongwith actionscript 3.0 and mxml.</description> 
    </book> 
    <book isbn="0132149184"> 
     <title>Java Software Solutions</title> 
     <description> 
      Complete book full of case studies on business solutions and design concepts while building mission critical 
      business applications. 
     </description> 
    </book> 

如何将它使用XQuery转换成CSV格式? CSV由Microsoft Excel使用,

所以它将由逗号(,)分隔,字符和特殊字符应该被转义。

回答

4

纯的XPath 2.0表达式

for $b in /*/book 
    return 
     concat(escape-html-uri(string-join(($b/@isbn, 
              $b/title, 
              $b/description 
             ) 
              /normalize-space(), 
             ",") 
          ), 
      codepoints-to-string(10)) 

XSLT 2 - 基于验证:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:sequence select= 
    "for $b in /*/book 
     return 
     concat(escape-html-uri(string-join(($b/@isbn, 
              $b/title, 
              $b/description 
              ) 
               /normalize-space(), 
              ',') 
           ), 
       codepoints-to-string(10))"/> 
</xsl:template> 
</xsl:stylesheet> 

当这个变换所提供的XML文档施加(从校正其畸形):

<books> 
    <book isbn="1590593049"> 
     <title>Extending Flash MX 2004</title> 
     <description> 
     Using javascript alongwith actionscript 3.0 and mxml.</description> 
    </book> 
    <book isbn="0132149184"> 
     <title>Java Software Solutions</title> 
     <description> 
      Complete book full of case studies on business solutions and design concepts while building mission critical 
      business applications. 
     </description> 
    </book> 
</books> 

想要的,正确的结果产生

1590593049,Extending Flash MX 2004,Using javascript alongwith actionscript 3.0 and mxml. 
0132149184,Java Software Solutions,Complete book full of case studies on business solutions and design concepts while building mission critical business applications. 

更新

在评论中OP已要求任何文本逗号由报价和(包围之后)任何报价被两个报价取代,最后,如果报告结果包含wholw,它必须包含(单个)报价。

这里是产生此纯的XPath 2.0表达式:

for $b in /*/book, 
    $q in codepoints-to-string(34), 
    $NL in codepoints-to-string(10), 
    $isbn in normalize-space(replace($b/@isbn, ',', concat($q,',',$q))), 
    $t in normalize-space(replace($b/title, ',', concat($q,',',$q))), 
    $d in normalize-space(replace($b/description, ',', concat($q,',',$q))), 
    $res in 
    escape-html-uri(string-join(($isbn,$t,$d), ',')), 
    $res2 in replace($res, $q, concat($q,$q)) 
    return 
    if(contains($res2, $q)) 
     then concat($q, $res2, $q, $NL) 
     else concat($res2, $NL) 

当该XPath表达式对这种评估(扩展用一个新的测试例)的XML文档:

<books> 
    <book isbn="1590593049"> 
     <title>Extending Flash MX 2004</title> 
     <description> 
     Using javascript alongwith actionscript 3.0 and mxml.</description> 
    </book> 
    <book isbn="0132149184"> 
     <title>Java Software Solutions</title> 
     <description> 
      Complete book full of case studies on business solutions and design concepts while building mission critical 
      business applications. 
     </description> 
    </book> 
    <book isbn="XX1234567"> 
     <title>Quotes and comma</title> 
     <description> 
      Hello, World from "Ms-Excel" 
     </description> 
    </book> 
</books> 

想要的,会产生正确的结果:

1590593049,Extending Flash MX 2004,Using javascript alongwith actionscript 3.0 and mxml. 
0132149184,Java Software Solutions,Complete book full of case studies on business solutions and design concepts while building mission critical business applications. 
"XX1234567,Quotes and comma,Hello"","" World from ""Ms-Excel""" 
+0

,但如果它是纯XPath 2,它不会将' '解释为换行符 – BeniBela

+0

@BeniBela,您的问题不清楚 - 我更新了我的答案使用相同的XPath表达式的XSLT转换如果这不是一个合法的XPath表达式,将会出现错误,但是转换没有任何问题。 –

+0

那么,如果你将它包含在XSLT中,它就不再是*纯粹* XPath。然后XML解析器替换&#xa。如果你只运行没有XSLT的* pure * XPath,你会得到:'1590593049,扩展Flash MX 2004,使用JavaScript以及actionscript 3.0和mxml。 0132149184,Java软件解决方案,完整的书籍业务解决方案和设计概念的案例研究,同时构建关键业务应用程序。 '在示例 – BeniBela

4

假设你的XML是在变量$books,你可以在一个新行使用此创建每本书节点CSV文件:

declare function local:my-replace($input) { 
    for $i in $input 
    return '"' || replace($i, '"', '""') || '"' 
}; 
for $book in $books//book 
return string-join(local:my-replace(($book/@isbn, $book/title, $book/description)), ",") || '&#xa;' 

string-join地连接了不同的字符串,本地函数my-replace在替换值根据你的规格的顺序。

+0

您发布的上述代码段在正常情况下效果很好,但在CSV中,字段由逗号(,)指定。现在,如果文本本身包含逗号,那么当该逗号是文本的一部分时,例如说明单元格或标题单元格的一部分,则excel会将该逗号解释为逗号分隔符。 一个典型的方法是,通过在双引号之前加双引号来避免逗号(012): Hello,来自“Ms-Excel”的世界将是:“Hello,World from”“Ms -Excel“”“。如何逃避这种方式?感谢您的大力帮助。 –

+0

我刚刚编辑了我的答案,以反映您添加的规范。我刚创建了一个用户定义的函数my-replace,它在开头添加了一个”和每个元素的结尾,并用“”代替“ – dirkk