python - 使用 SQL 查询更新 XML

标签 python sql xml

假设我们有以下 XML 文件:

from lxml import etree
root = etree.fromstring("""
    <a>
        <b>
            <c>Hello</c>
            <d>1234</d>
        </b>
        <b>
            <c>Bonjour</c>
            <d>5678</d>
        </b>        
    </a>
    """)
怎么可能用类似 SQL 的查询语言更新 XML?
示例(伪代码):
etree.query("""UPDATE a.b SET c.text = 'foo' WHERE d.text = '5678'""")
甚至更复杂的链式查询,例如:
UPDATE a.b SET c.text = (SELECT ... FROM ... WHERE ...) WHERE d.text = '5678'
目标是能够使用类似 SQL 的语法仅用一两行代码来修改复杂的 XML 文档。旁注:作为比较,使用 lxml 手动执行此操作, find等工作,但要长得多。

最佳答案

考虑 XSLT ,一种旨在转换 XML 文档的专用语言,它共享 SQL 的一些属性:

  • 可以被通用应用层调用的专用语言。
  • 行业语言不限于 Python 等任何语言,可以通过 standalone processors 运行比如撒克逊和夏兰。
  • 声明式风格和语义,可以从应用层接收参数。

  • Python的lxml可以运行 XSLT 1.0 脚本,这些脚本只是特殊的 XML 文件。要回答您的第一个查询,请使用 <xsl:choose> 的条件 XSLT 副本。 .
    加载文档
    from lxml import etree
    
    root = etree.fromstring("""\
        <a>
            <b>
                <c>Hello</c>
                <d>1234</d>
            </b>
            <b>
                <c>Bonjour</c>
                <d>5678</d>
            </b>        
        </a>""")
    
    xsl = etree.fromstring("""\
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <!-- INITIALIZE PARAMETERS -->
        <xsl:param name="c_val"/>
        <xsl:param name="d_val"/>
    
        <!-- IDENTITY TRANSFORM -->
        <xsl:template match="node()|@*">
           <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
           </xsl:copy>
        </xsl:template>
    
        <!-- CONDITIONALLY UPDATE <c> -->
        <xsl:template match="c">
           <xsl:copy>
             <xsl:choose>
                 <xsl:when test="following-sibling::d = $d_val">
                       <xsl:value-of select="$c_val"/>
                 </xsl:when>
                 <xsl:otherwise>
                       <xsl:value-of select="text()"/>
                 </xsl:otherwise>  
             </xsl:choose>
           </xsl:copy>
        </xsl:template>    
    </xsl:stylesheet>""")
    
    运行改造
    # INITIALIZE TRANSFORMER
    transformer = etree.XSLT(xsl)
    
    # TRANSFORM WITH PARAMETERS
    result = transformer(
                root, 
                c_val=etree.XSLT.strparam("foo"),
                d_val=etree.XSLT.strparam("5678")
             )
    
    # OUTPUT RESULT TO CONSOLE
    print(result)
    # <a>
    #   <b>
    #     <c>Hello</c>
    #     <d>1234</d>
    #   </b>
    #   <b>
    #     <c>foo</c>
    #     <d>5678</d>
    #   </b>
    #</a>
    
    不太清楚你的第二个查询。但是如果需要从不同的 XML 文档(对应于不同的 SQL 表)进行查询,XSLT 会维护 document()函数,可以在大多数地方调用,包括参数。调整下面的 XPath。
    <xsl:param name="c_val">
       <xsl:value-of select="document('other.xml')/a/b/c[1]">
    </xsl:param>
    
    如果没有通过 c_val从应用层,一定要在 Python 中删除该参数,否则你会覆盖上面。

    关于python - 使用 SQL 查询更新 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66185262/

    相关文章:

    python - 如何将 QWidget 与 QItemDelegate 和 QTableView 一起使用

    python - 从皇帝运行 rbtimer

    sql - Access 查询 : Running total without using DSum (or another approach all together)?

    python - 使用 lxml 解析 XML

    python - STORAGE [main] In File::open(),::open for '/docker-entrypoint-initdb.d/create_user.js' 失败,权限被拒绝

    python - 如何使用 numpy 将一个小矩阵添加到一个大矩阵中?

    sql - 在 Sequelize 模型中使用 Postgres 生成的列

    SQL - 拆分数据行并分配分值

    javascript - 更新值后如何通过 jQuery 输出 XML 节点?

    java - XML 响应时间 ejabberd