简体   繁体   English

使用python从SQL表生成XML

[英]Using python to generate XML from SQL tables

I have some XML as follows: 我有一些XML,如下所示:

<dd>
    <persson>
        <name>sam</name>
        <tel>9748</tel>
    </persson>
    <cat>
        <name>frank</name>
    </cat>
</dd>

I parsed it into two SQL tables, one for the tags and one for the pcdata. 我将其解析为两个SQL表,一个用于标记,一个用于pcdata。 The start and stop columns represent the position the tag appears at and ends. “开始”和“停止”列代表标签出现和结束的位置。

Tags:
 start | stop |  tag   
-------+------+--------
     3 |    5 | name
     6 |    8 | tel
     2 |    9 | persson
    11 |   13 | name
    10 |   14 | cat
     1 |   15 | dd
(6 rows)

Pcdata:
 pos | pcdata 
-----+--------
   4 | sam
   7 | 9748
  12 | frank
(3 rows)

Now i'd like to parse this database back into XML in the original form. 现在,我想将此数据库解析为原始格式的XML。 I want to write a function that takes both tables and writes the XML out in a file. 我想编写一个同时使用两个表并将XML写入文件的函数。 I'm using python and psycopg2 to do this. 我正在使用python和psycopg2来做到这一点。

H'mmm having decoded your "columns": 嗯,您已经解码了您的“列”:

<dd><persson><name>sam</name><tel>9748</tel></persson>
1   2        3     4  5      6    7   8     9                    
<cat><name>frank</name></cat></dd>
10   11    12   13     14    15

I have some questions for you: How did you do that? 我有一些问题要问您:您是如何做到的? Why did you do that? 你为什么这么做? Exactly what do you want to achieve? 您到底想实现什么? Note that your question title is rather misleading -- "SQL tables" are merely where you have parked your peculiar representation of the data. 请注意,您的问题标题颇具误导性-“ SQL表”仅是存放数据的特殊表示的地方。

Here's some pseudocode to do what you want to do: 这是一些伪代码,可以执行您想做的事情:

pieces = []
result = cursor.execute("select * from tags;")
for start, step, tag in result:
    pieces.append((start, "<" + tag + ">"))
    pieces.append((stop, "</" + tag + ">"))
result = cursor.execute("select * from pcdata;")
for pos, pcdata in result:
    pieces.append((pos, pcdata))
pieces.sort()
xml_stream = "".join(piece[1] for piece in pieces)
your_file_object.write(xml_stream)

In answer to the question about whether the above would put the "positions" in the output stream: No it won't; 在回答有关上述内容是否会将“位置”放入输出流的问题时: the following snippet shows it working. 以下代码段显示了它的工作原理。 The positions are used only to get the soup sorted into the correct order. 这些位置仅用于将汤分类为正确的顺序。 In the "join", piece[0] refers to the position, but it isn't used, only piece[1] which is the required text. 在“连接”中, piece[0]指的是位置,但未使用它,仅piece[1]是必需的文本。

>>> pieces
[(3, '<name>'), (4, 'sam'), (5, '</name>')]
>>> ''.join(piece[1] for piece in pieces)
'<name>sam</name>'

Relenting on the SQL comment-question: 处理SQL注释问题:

Although shown with SQLite, this is bog-standard SQL. 尽管与SQLite一起显示,但这是沼泽标准SQL。 If your database doesn't grok || 如果您的数据库没有运行|| as the concatenation operator, try + . 作为串联运算符,请尝试+

Question that you forgot to ask: "How do I get a <?xml blah-blah ?> thingie up the front?". 您忘了问的问题:“如何让<?xml blah-blah ?>东西放在前面?”。 Answer: See below. 答:见下文。

console-prompt>sqlite3
SQLite version 3.6.14
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table tags (start int, stop int, tag text);
sqlite> insert into tags values(3,5,'name');
sqlite> insert into tags values(6,8,'tel');
sqlite> insert into tags values(2,9,'persson');
sqlite> insert into tags values(11,13,'name');
sqlite> insert into tags values(10,14,'cat');
sqlite> insert into tags values(1,15,'dd');
sqlite> create table pcdata (pos int, pcdata text);
sqlite> insert into pcdata values(4,'sam');
sqlite> insert into pcdata values(7,'9748');
sqlite> insert into pcdata values(12,'frank');
sqlite> select datum from (
   ...>     select 0 as posn, '<?xml version="1.0" encoding="UTF-8"?>' as datum
   ...>     union
   ...>     select start as posn, '<' || tag || '>' as datum from tags
   ...>     union
   ...>     select stop as posn, '</' || tag || '>' as datum from tags
   ...>     union
   ...>     select pos as posn, pcdata as datum from pcdata
   ...>     )
   ...> order by posn;
<?xml version="1.0" encoding="UTF-8"?>
<dd>
<persson>
<name>
sam
</name>
<tel>
9748
</tel>
</persson>
<cat>
<name>
frank
</name>
</cat>
</dd>
sqlite>

The simple answer is don't. 简单的答案是不。 If you are using Postgres 8.3 or above, build the XML using SQL. 如果您使用的是Postgres 8.3或更高版本,请使用SQL构建XML。 It will be much easier. 这样会容易得多。

http://www.postgresql.org/docs/current/static/functions-xml.html http://www.postgresql.org/docs/current/static/functions-xml.html

First off, if Postgres includes mechanisms to create XML for you, use them. 首先,如果Postgres包括为您创建XML的机制,请使用它们。

Second off, don't use string manipulation to create XML unless you really know what you're doing. 其次,除非您真的知道自己在做什么,否则不要使用字符串操作来创建XML。 And even then, don't. 即使那样,也不要这样。 Just concatenating string values from your database will produce poorly-formed XML if any column contains an ampersand, for instance. 例如,如果任何列包含“与”号,则仅连接数据库中的字符串值将产生格式不正确的XML。

Unless you will be processing too much data to fit in memory, use John Machin's approach to parse the data into elements and lxml.etree to create the actual XML elements. 除非您要处理太多数据以致无法容纳在内存中,否则请使用John Machin的方法将数据解析为元素,然后使用lxml.etree创建实际的XML元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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