2016-07-17 4 views
1

Ich verwende Python und requests Bibliothek, um POST Anfragen mit einer XML-Datei zu senden. Meine XML-Datei sieht wie folgt aus:Variablen an XML-Zeichenfolge anhängen, die in einer Variablen gespeichert wird

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>""" 

Wie man dort sehen kann eine property_name Variable ist, die tatsächlich ist, wird durch eine Funktion erzeugt werden.

Jetzt habe ich die property_name Variable manuell durch Verketten der XML-Zeichenfolge hinzugefügt. Aber da ich viele dieser Variablen haben werde, muss ich einen Weg finden, sie an der richtigen Position anzuhängen.

Was ist ein richtiger Weg, dies mit Python zu tun? Gibt es Bibliotheken oder empfohlene Techniken, um dies zu erreichen?

+1

Haben Sie versucht, '.format()'? –

+0

Was ist das XML-Datenmuster Ihres Servers? Meine Idee verwendet nicht 'property' Definition cos hat ein Update bekommen. Verwenden Sie " Adm2_NAME fff' unter 'Update-Abschnitt'. Vielleicht akzeptiert der Server Ihre 'Eigenschaft' nicht,' erzeugt einen ungültigen Schlüsselfehler'. Ihr Code hat keinen Fehler, muss aber das serverseitige Muster deklarieren. Also nenne vielleicht "Primärschlüssel" und keine "Eigenschaft". – dsgdfg

Antwort

1

Betrachten Sie XSLT, die spezielle Sprache für die Transformation von XML-Dateien, um Teile anderer XML-Dateien in die XML-Hauptdatei einzufügen. Pythons Drittanbietermodul lxml kann XSLT 1.0-Skripts verarbeiten. XSLT verwaltet die document()-Funktion und ermöglicht die Abfrage von Dokumenten im selben oder Unterverzeichnis. Um diesen Ansatz auszuführen, müssen Sie jedoch die kleineren XML-Zeichenfolgen auf einem Datenträger oder einer Datei sowie ein XSLT-Skript speichern, um die Verarbeitung von Dokumenten übergreifend zu verarbeiten.

Eine weitere wichtige Voraussetzung ist, dass die kleineren XML-Strings ihren Namespace im Root-Tag <wfs:Property xmlns:wfs="http://www.opengis.net/wfs"> definieren müssen, damit das vor der Ausgabe an die Datei verkettet wird. Folgen Sie der Eigenschaftsroutine und fügen Sie eine Zeile <xsl:copy-of select="document('OtherXML.xml')"> in xsl template hinzu, die mit dem angegebenen übergeordneten Knoten übereinstimmt, um weitere XML-Zeichenfolgen in Dateien in XSLT hinzuzufügen.

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() 

Alternativ noch XSLT verwenden, können Sie jede mögliche Notwendigkeit umgehen für document() oder einzelne Strings auf der Festplatte zu speichern. Bei diesem Ansatz verketten Sie einfach die kleineren XML-Zeichenfolgen mit der Vorlagenübereinstimmung von 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() 
+0

Ich bin ein wenig verwirrt mit dem Workflow. Warum machst du: PARSE-MAIN-XML-STRING? Ich muss auch mehrere property_name an die ursprüngliche XML anhängen. Dieser Code funktioniert derzeit, wenn ich nur einen property_name habe. Recht? – user1919

+0

Auch die # XSL STRING enthält Elemente, die ich nicht in meinem XML habe. Woher kommen all diese Elemente? – user1919

+1

Für die erste Art von Dokumentansatz, fügen Sie eine Kopierzeile oder jede Eigenschaft (die ich erwähne) hinzu: ''. Fügen Sie für den zweiten Optionsstring die anderen Eigenschaften an der gleichen Stelle hinzu, an der 'format()' mehrere Elemente annehmen kann, aber entsprechende '{0}, {1}, ...'. – Parfait

Verwandte Themen