我正在使用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执行此操作的正确方法是什么?是否有可用的库或推荐的技术来实现这一目标?
答案 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()