嵌套XML加入MySQL表

时间:2013-07-19 15:04:06

标签: mysql sql xml nested

我有一些嵌套字段的数据,我想导入MySQL。可能有很多文件,所以任何可重复的脚本语言都是值得赞赏的。看起来这应该比我做的容易,但我找不到一个好的答案。

我相信最简洁的方法是使用连接表,尽管在父表中还有一个元素也是很好的,比如它是否有类型代码" A1"在下面的示例中。

这里回答了类似的查询Parsing nested xml into denormalized table,除了MySQL不是,并且数据带有唯一标识符。我的数据面临的挑战之一是数据中没有唯一标识符来创建用于连接表的主键。

以下示例数据。在这里,doc-id和assignor标签必须是单独的表并加入。这些数据有一个DTD,我不包括它的价值。任何意见都非常感谢!

 <?xml version="1.0" encoding="UTF-8"?>
<assignment>
    <assignment-record>
        <reel-no>28879</reel-no>
        <frame-no>97</frame-no>
        <last-update-date><date>20120903</date></last-update-date>
        <recorded-date><date>20120830</date></recorded-date>
        <page-count>4</page-count>
        <correspondent>
            <name>LEE, HONG, DEGERMAN, KANG &amp; WAIMEY</name>
            <address-1>660 S. FIGUEROA ST., 23RD FL.</address-1>
            <address-2>LOS ANGELES, CA 90017</address-2>
        </correspondent>
        <conveyance-text>ASSIGNMENT OF ASSIGNORS INTEREST (SEE DOCUMENT FOR DETAILS).</conveyance-text>
    </assignment-record>
    <assignors>
        <assignor>
            <name>WOO, SUNGHO</name>
            <execution-date><date>20120806</date></execution-date>
        </assignor>
            <assignor>
                <name>CHOI, JAEYOUNG</name>
                <execution-date><date>20120806</date></execution-date>
        </assignor>
    </assignors>
    <docproperties>
        <property>
            <document-id>
                <country>US</country>
                <doc-number>13277056</doc-number>
                <kind>X0</kind>
                <date>20111019</date>
            </document-id>
            <document-id>
                <country>US</country>
                <doc-number>20120213136</doc-number>
                <kind>A1</kind>
                <date>20120823</date>
            </document-id>
            <title lang="en">SYSTEMS AND METHODS FOR CONTROLLING SENSOR DEVICES IN MOBILE DEVICES</title>
     </property>
    </docproperties>
</assignment>
</xml>

1 个答案:

答案 0 :(得分:2)

由于这个三年前未回答的问题最近被其他用户提出,我继续代表社区回答,因为原来的OP不再活跃。

对于未来的读者,无论何时需要压缩嵌套的XML文件以进行平面文件导入(例如数据库表),都要考虑XSLT,这是用于操作XML文件的转换语言。实际上,所有通用语言都有一些用于XSLT 1.0处理的库,包括Python,PHP,Perl,Java,C#,VB等。

当OP提到Python时,下面的示例使用第三方lxml模块来展平XML文件。要生成与<assignor><document-id>数据相关联的唯一ID,请使用ancestor运行XSLT脚本中的XPath以检索 reel-no 值来自<assignment-record>,两个节点共享为兄弟。这类似于发布链接中的TSQL解决方案。

XSLT 脚本(另存为.xsl以在Python中引用)

转让人转型

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>

  <xsl:template match="/assignment">
    <xsl:copy>      
      <xsl:apply-templates select="descendant::assignor"/>
    </xsl:copy>
  </xsl:template>  

  <xsl:template match="assignor">
    <xsl:copy>
      <assign_id>
          <xsl:value-of select="ancestor::assignment/assignment-record/reel-no"/>
      </assign_id>
      <xsl:copy-of select="name"/>
      <xsl:copy-of select="execution-date/date"/>        
    </xsl:copy>
  </xsl:template>

</xsl:transform>

文档ID转换

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>

  <xsl:template match="/assignment">
    <xsl:copy>
      <xsl:apply-templates select="descendant::document-id"/>
    </xsl:copy>
  </xsl:template>  

  <xsl:template match="document-id">
    <xsl:copy>
      <assign_id>
          <xsl:value-of select="ancestor::assignment/assignment-record/reel-no"/>
      </assign_id>
      <xsl:copy-of select="*"/>        
    </xsl:copy>
  </xsl:template>

</xsl:transform>

Python 脚本(将源代码转换为两个文件)

import lxml.etree as ET

dom = ET.parse('Assignment.xml')
xslt = ET.parse('Assignor_XSLT_Script.xsl')

transform = ET.XSLT(xslt)
newdom = transform(dom)    

xmlfile = open(os.path.join(cd, 'Assignor.xml'),'wb')
xmlfile.write(newdom)
xmlfile.close()    

xslt = ET.parse('Document-Id_XSLT_Script.xsl')    
transform = ET.XSLT(xslt)
newdom = transform(dom)

xmlfile = open(os.path.join(cd, 'Document-Id.xml'),'wb')
xmlfile.write(newdom)
xmlfile.close()    

XML 输出(现在可以有效地使用MySQL&#39的LOAD XML)

<?xml version="1.0" encoding="UTF-8"?>
<assignment>
  <assignor>
    <assign_id>28879</assign_id>
    <name>WOO, SUNGHO</name>
    <date>20120806</date>
  </assignor>
  <assignor>
    <assign_id>28879</assign_id>
    <name>CHOI, JAEYOUNG</name>
    <date>20120806</date>
  </assignor>
</assignment>


<?xml version="1.0" encoding="UTF-8"?>
<assignment>
  <document-id>
    <assign_id>28879</assign_id>
    <country>US</country>
    <doc-number>13277056</doc-number>
    <kind>X0</kind>
    <date>20111019</date>
  </document-id>
  <document-id>
    <assign_id>28879</assign_id>
    <country>US</country>
    <doc-number>20120213136</doc-number>
    <kind>A1</kind>
    <date>20120823</date>
  </document-id>
</assignment>