在XML字符串上追加变量,该变量存储在变量中

时间:2016-07-17 08:19:12

标签: python xml

我正在使用Python和requests库来发送带有XML文件的POST个请求。我的XML文件如下所示:

property_name = """<wfs:Property>
  <wfs:Name>Adm2_NAME</wfs:Name>
  <wfs:Value>fff</wfs:Value>
</wfs:Property>"""

xml = """<wfs:Transaction service="WFS" version="1.0.0"
  xmlns:ogc="http://www.opengis.net/ogc"
  xmlns:wfs="http://www.opengis.net/wfs">
  <wfs:Update typeName="geonode:tjk_nhr_shockriskscore">
  """ + property_name + """
    <ogc:Filter>
      <ogc:FeatureId fid="tjk_nhr_shockriskscore.2"/>
    </ogc:Filter>
  </wfs:Update>
</wfs:Transaction>"""

正如您所看到的,有一个property_name变量实际上将由函数生成。

现在我通过连接XML字符串手动附加property_name变量。但由于我将拥有许多这些变量,我需要找到一种方法将它们附加到正确的位置。

使用Python执行此操作的正确方法是什么?是否有可用的库或推荐的技术来实现这一目标?

1 个答案:

答案 0 :(得分:1)

考虑转换XML文件的特殊目的语言XSLT,将其他XML的部分附加到主XML文件中。 Python的第三方模块lxml可以处理XSLT 1.0脚本。 XSLT维护document()功能,允许查询相同或子目录中的文档。但是,为了运行此方法,必须将较小的XML字符串保存到磁盘或文件以及XSLT脚本以处理跨文档处理。

另一个重要的要求是较小的XML字符串必须在根标记<wfs:Property xmlns:wfs="http://www.opengis.net/wfs">中定义其名称空间,以便在输出到文件之前将其连接起来。要在XSLT中添加其他XML字符串转换文件,请遵循属性例程,并在与指定父节点匹配的xsl模板中添加一行<xsl:copy-of select="document('OtherXML.xml')">

import lxml.etree as et

# SAVE XML TO FILE
nmsp = 'xmlns:wfs="http://www.opengis.net/wfs"'
property_name = '''<wfs:Property {}>
  <wfs:Name>Adm2_NAME</wfs:Name>
  <wfs:Value>fff</wfs:Value>
</wfs:Property>'''
xmlfile = open('Property.xml','w')
xmlfile.write(property_name.format(nmsp))
xmlfile.close()

# SAVE XSL TO FILE
xslstr = '''<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="wfs:Update">
    <xsl:copy>
      <xsl:copy-of select="document('Property.xml')"/>
      <xsl:apply-templates />
    </xsl:copy>  
  </xsl:template>        
</xsl:transform>'''
xslfile = open('XSLTScript.xsl','w')
xslfile.write(xslstr)
xslfile.close()

# PARSE MAIN XML STRING
xml = '''<wfs:Transaction service="WFS" version="1.0.0"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:wfs="http://www.opengis.net/wfs">
<wfs:Update typeName="geonode:tjk_nhr_shockriskscore">        
  <ogc:Filter>
    <ogc:FeatureId fid="tjk_nhr_shockriskscore.2"/>
  </ogc:Filter>
</wfs:Update>
</wfs:Transaction>'''
dom = et.fromstring(xml)

# TRANSFORM XML
xsl = et.parse('XSLTScript.xsl')
transform = et.XSLT(xsl)
newdom = transform(dom)

print(newdom)
# <?xml version="1.0"?>
# <wfs:Transaction xmlns:ogc="http://www.opengis.net/ogc" 
#   xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.0.0">
#   <wfs:Update>
#     <wfs:Property>
#       <wfs:Name>Adm2_NAME</wfs:Name>
#       <wfs:Value>fff</wfs:Value>
#     </wfs:Property>
#     <ogc:Filter>
#       <ogc:FeatureId fid="tjk_nhr_shockriskscore.2"/>
#     </ogc:Filter>
#   </wfs:Update>
# </wfs:Transaction>

# OUTPUT FINAL XML
xmlfile = open('Final.xml','wb')
xmlfile.write(newdom)
xmlfile.close()

或者,仍然使用XSLT,您可以绕过对document()的任何需要或将单个字符串保存到磁盘。在这种方法中,您只需将较小的XML字符串连接到XSLT的模板匹配。

import lxml.etree as et

# XML STRING
property_name = '''<wfs:Property>
  <wfs:Name>Adm2_NAME</wfs:Name>
  <wfs:Value>fff</wfs:Value>
</wfs:Property>'''

# XSL STRING
xslstr = '''<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ogc="http://www.opengis.net/ogc" xmlns:wfs="http://www.opengis.net/wfs">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="wfs:Update">
    <xsl:copy>
      {}
      <xsl:apply-templates />
    </xsl:copy>  
  </xsl:template>    
</xsl:transform>'''.format(property_name)

# PARSE MAIN XML STRING
xmlstr = '''<wfs:Transaction service="WFS" version="1.0.0"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:wfs="http://www.opengis.net/wfs">
<wfs:Update typeName="geonode:tjk_nhr_shockriskscore">        
  <ogc:Filter>
    <ogc:FeatureId fid="tjk_nhr_shockriskscore.2"/>
  </ogc:Filter>
</wfs:Update>
</wfs:Transaction>'''
dom = et.fromstring(xmlstr)

# TRANSFORM XML
xsl = et.fromstring(xslstr)
transform = et.XSLT(xsl)
newdom = transform(dom)

print(newdom)
# <?xml version="1.0"?>
# <wfs:Transaction xmlns:ogc="http://www.opengis.net/ogc" 
# xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.0.0">
#   <wfs:Update>
#     <wfs:Property>
#       <wfs:Name>Adm2_NAME</wfs:Name>
#       <wfs:Value>fff</wfs:Value>
#     </wfs:Property>
#     <ogc:Filter>
#       <ogc:FeatureId fid="tjk_nhr_shockriskscore.2"/>
#     </ogc:Filter>
#   </wfs:Update>
# </wfs:Transaction>

# OUTPUT FINAL XML
xmlfile = open('Final.xml','wb')
xmlfile.write(newdom)
xmlfile.close()
相关问题