【问题标题】:Map XML to SQL for easy export将 XML 映射到 SQL 以便于导出
【发布时间】:2022-08-03 15:56:46
【问题描述】:

我有以下想要映射到关系模型的 XML,以便我可以再次查询和重新导出相同的 XML。

<?xml version=\"1.0\" encoding=\"UTF-8\"?>

<document name=\"001_COUNTERPARTY_CATEGORY_UK_BOE\" date=\"2022-06-30\" level=\"01-01-xx-xx-xx\">

<PARTY F=\"01-01\" PARTY_ID=\"201_A_Prod_P\" />
<PARTY_FIELD F1=\"01-01\" PARTY_ID=\"201_A_Prod_P\" fieldname=\"CTY0\" value=\"IR\"/>
<PARTY_FIELD F1=\"01-01\" PARTY_ID=\"201_A_Prod_P\" fieldname=\"CTY1\" value=\"IR\"/>
<PARTY_FIELD F1=\"01-01\" PARTY_ID=\"201_A_Prod_P\" fieldname=\"SIE\" value=\"64_19\"/>
<PARTY_FIELD F1=\"01-01\" PARTY_ID=\"201_A_Prod_P\" fieldname=\"SIE\" value=\"0\"/>

<CHANNEL F=\"01-01\" CHANNEL_ID=\"201_A_Prod_PRODUCT\"/>
<CHANNEL_FIELD F=\"01-01\" CHANNEL_ID=\"201_A_Prod_PRODUCT\" fieldname=\"PRD013\" value=\"1010\"/>
<CHANNEL_FIELD F=\"01-01\" CHANNEL_ID=\"201_A_Prod_PRODUCT\" fieldname=\"CUR007\" value=\"GBP\"/>
<CHANNEL_FIELD F=\"01-01\" CHANNEL_ID=\"201_A_Prod_PRODUCT\" fieldname=\"PARTY_ID30\" value=\"201_A_Prod_P\"/>

<RATE F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\"/>
<RATE_FIELD F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\" fieldname=\"CHANNEL_ID0\" value=\"201_A_Prod_PRODUCT\"/>
<RATE_FIELD F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\" fieldname=\"C213\" value=\"100000\"/>    
<RATE_FIELD F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\" fieldname=\"C214\" value=\"100000\"/>    
<RATE_FIELD F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\" fieldname=\"C215\" value=\"100000\"/>    
<RATE_FIELD F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\" fieldname=\"PTY001\" value=\"1\"/>
<RATE_FIELD F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\" fieldname=\"PTY002\" value=\"1\"/>
<RATE_FIELD F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\" fieldname=\"PTY006\" value=\"0\"/>
<RATE_FIELD F=\"01-01\" RATE_ID=\"201_A_Prod_PRODUCT\" fieldname=\"PTY025\" value=\"0\"/>

</document>

PARTY AND CHANNEL 通过 CHANNEL_FIELD\'s 属性相互关联 PARTY_ID30

CHANNEL 通过RATE_FIELD\'s 属性CHANNEL_ID0RATE 相关联

我创建了如下表,但我无法像给定的 xml 那样查询它们以导出:

PARTY (F,PARTY_ID,PARTY_FIELDNAME,PARTY_FIELDVALUE)
CHANNEL (F,CHANNEL_ID,CHANNEL_FIELDNAME,CHANNEL_FIELDVALUE)
PRODUCT (F,RATE_ID,RATE_FIELDNAME,RATE_FIELDVALUE)

我需要更改架构以让我查询和导出行以创建此 xml,或者构建查询以生成与上述架构中的 xml 顺序相同的行。

另一种方法是导出csv中的行,然后使用python生成xml,但是对于大型数据集来说会是开销

  • 一个特定的 CHANNEL_FIELD fieldname 作为外键的数据模型有点混乱。您确定要坚持使用此模型吗?这真的很奇怪,即使对于 XML 也是如此。
  • @digitalarbeiter 我理解,但是源系统生成数据是这样的

标签: python mysql sql xml


【解决方案1】:

我会将其拆分为parties/party_fields 表(频道和费率相同):

CREATE TABLE parties (id VARCHAR(32), f TEXT, PRIMARY KEY(id));
CREATE TABLE party_fields (party_id VARCHAR(32), f TEXT, fieldname TEXT, value TEXT, FOREIGN KEY(party_id) REFERENCES parties(id));

(旁注:从您的示例数据看来,您甚至不能对 (party_id, fieldname) 设置唯一约束,因为字段名“SIE”出现了两次。)

然后使用 Python 的 xml.etree.ElementTree 遍历 XML 文档并根据元素 tag 生成 INSERT 语句(假设您有一个 cursor,我稍微掩盖了 MySQL 客户端代码):

import xml.etree.ElementTree as et
for node in et.fromstring(the_long_xml_string):
    if node.tag == "PARTY":
        cursor.execute(
            "INSERT INTO parties (id, f) VALUES (%s, %s)",
            (node.attrib["PARTY_ID"], node.attrib["F"]),
        )
    elif node.tag == "PARTYFIELD":
        cursor.execute(
            "INSERT INTO party_fields (party_id, f, fieldname, value) VALUES (%s, %s, %s, %s)",
            (node.attrib["PARTY_ID"], node.attrib["F"], node.attrib["fieldname"], node.attrib["value"]),
        )
    elif node.tag == "CHANNEL":
        ...
cursor.commit()

坦率地说,对于这种 XML 结构,我不会为字段名称为 PARTY_ID30 的方字段中的外键而烦恼 - 我认为这真的会弄乱你的数据库模式(好吧,至少我想不出一种方法来做到这一点干净;也许其他人可以)。

现在要(重新)生成 XML,您可以从数据库中迭代各方:

current_party_id = None
for row in cursor.execute("SELECT * FROM party_fields ORDER BY party_id ASC"):
    if row["party_id"] != current_party_id:
        out.write(f'<PARTY PARTY_ID="{row["party_id"]}" F="{row["f"]} />\n"')
        current_party_id = row["party_id"]
    out.write(f'<PARTY_FIELD PARTY_ID="{row["party_id"]}" F="{row["f"]}" fieldname="{row["fieldname"]}" value="{row["value"]}" />\n')

...频道和费率也是如此。

希望这可以帮助。如果您还有其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    相关资源
    最近更新 更多