Frage

Wie kann ich groovy verwenden in XML suchen + ersetzen?

Ich brauche etwas so kurz / einfach wie möglich, da ich an die Tester diesen Code geben würde für ihr SoapUI Scripting.

Genauer gesagt, wie kann ich mich wenden:

<root><data></data></root>

in:

<root><data>value</data></root>
War es hilfreich?

Lösung

Einige der Dinge, die Sie mit einem XSLT tun können Sie auch mit irgendeiner Form von ‚Suchen & Ersetzen‘ tun können. Es hängt alles davon ab, wie komplex das Problem ist und wie ‚generische‘ Sie wollen die Lösung implementieren. Um Ihr eigenes Beispiel etwas allgemeineren zu machen:

xml.replaceFirst("<Mobiltlf>[^<]*</Mobiltlf>", '<Mobiltlf>32165487</Mobiltlf>')

Die Lösung Sie wählen, ist bis zu Ihnen. In meiner eigenen Erfahrung (für sehr einfache Probleme) einfache String-Lookups verwenden ist schneller als mit regulären Ausdrücken, die eine fullblown XSLT-Transformation (macht tatsächlich Sinn) als die Verwendung von wieder schneller ist.

Andere Tipps

Nach einiger rasenden Codierung sah ich das Licht und tat wie diese

import org.custommonkey.xmlunit.Diff
import org.custommonkey.xmlunit.XMLUnit

def input = '''<root><data></data></root>'''
def expectedResult = '''<root><data>value</data></root>'''

def xml = new XmlParser().parseText(input)

def p = xml.'**'.data
p.each{it.value="value"}

def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(xml)
def result = writer.toString()

XMLUnit.setIgnoreWhitespace(true)
def xmlDiff = new Diff(result, expectedResult)
assert xmlDiff.identical()

Leider wird diese erhalten nicht die Kommentare und Metadaten usw., von der ursprünglichen XML-Dokument, also werde ich einen anderen Weg finden müssen

habe ich einige einige Tests mit DOMCategory und es ist fast zu arbeiten. Ich kann das passieren ersetzen, aber einige infopath bezogene Kommentare verschwinden. Ich verwende ein Verfahren wie folgt aus:

def rtv = { xml, tag, value ->
    def doc     = DOMBuilder.parse(new StringReader(xml))
    def root    = doc.documentElement
    use(DOMCategory) { root.'**'."$tag".each{it.value=value} }
    return DOMUtil.serialize(root)    
}

auf einer Quelle wie folgt aus:

<?xml version="1.0" encoding="utf-8"?>
<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:FA_Ansoegning:http---ementor-dk-application-2007-06-22-" href="manifest.xsf" solutionVersion="1.0.0.14" productVersion="12.0.0" PIVersion="1.0.0.0" ?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?>
<application:FA_Ansoegning xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:application="http://corp.dk/application/2007/06/22/"
xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"
xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/200    8-04-14T14:31:48">
    <Mobiltlf></Mobiltlf>
  <E-mail-adresse></E-mail-adresse>
</application:FA_Ansoegning>

Das einzige, was aus dem Ergebnis fehlt, sind die

Das ist die beste Antwort, so weit und es gibt das richtige Ergebnis, also werde ich die Antwort akzeptieren :) Allerdings ist es ein wenig für mich zu groß. Ich glaube, ich habe besser zu erklären, dass die Alternative ist:

xml.replace("<Mobiltlf></Mobiltlf>", <Mobiltlf>32165487</Mobiltlf>")

Aber das ist nicht sehr xml'y so dass ich dachte, dass ich nach einer Alternative aussehen würde. Auch ich kann nicht sicher sein, dass der erste Tag ist leer die ganze Zeit.

Um die Attribute behalten nur Ihr kleines Programm wie diese ändern (Ich habe eine Probenquelle enthalten, es zu testen):

def input = """
<?xml version="1.0" encoding="utf-8"?>
<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:FA_Ansoegning:http---ementor-dk-application-2007-06-22-" href="manifest.xsf" solutionVersion="1.0.0.14" productVersion="12.0.0" PIVersion="1.0.0.0" ?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?>
<application:FA_Ansoegning xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:application="http://ementor.dk/application/2007/06/22/"
xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"
xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/200    8-04-14T14:31:48">
    <Mobiltlf  type="national" anotherattribute="value"></Mobiltlf>
  <E-mail-adresse attr="whatever"></E-mail-adresse>
</application:FA_Ansoegning>
""".trim()

def rtv = { xmlSource, tagName, newValue ->
    regex = "(<$tagName[^>]*>)([^<]*)(</$tagName>)"
    replacement = "\$1${newValue}\$3"
    xmlSource = xmlSource.replaceAll(regex, replacement)
    return xmlSource
}

input = rtv( input, "Mobiltlf", "32165487" )
input = rtv( input, "E-mail-adresse", "bob@email.com" )
println input

Ausführen dieses Skripts erzeugt:

<?xml version="1.0" encoding="utf-8"?>
<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:FA_Ansoegning:http---ementor-dk-application-2007-06-22-" href="manifest.xsf" solutionVersion="1.0.0.14" productVersion="12.0.0" PIVersion="1.0.0.0" ?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?>
<application:FA_Ansoegning xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:application="http://ementor.dk/application/2007/06/22/"
xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"
xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/200    8-04-14T14:31:48">
    <Mobiltlf  type="national" anotherattribute="value">32165487</Mobiltlf>
  <E-mail-adresse attr="whatever">bob@email.com</E-mail-adresse>
</application:FA_Ansoegning>

Beachten Sie, dass der passende regexp enthält nun 3 einfangenden Gruppen: (1) den Start-Tag (einschließlich Attributen), (2) was auch immer der 'alte' Inhalt Ihres Tages ist und (3) den End-Tag. Die Ersatzzeichenfolge bezieht sich auf diese erfassten Gruppen über die $ i Syntax (mit umgekehrten Schrägstrichen sie in der GString entweichen). Nur ein Tipp: Reguläre Ausdrücke sind sehr mächtige Tiere, es ist wirklich lohnenswert ist mit ihnen vertraut zu werden ;-)

.

Drei "offizielle" groovy Möglichkeiten der XML-Aktualisierung sind auf der Seite http: //groovy.codehaus. org / Verarbeitung + XML , Abschnitt "Aktualisieren von XML".

Von diesen drei scheint es nur DOMCategory Art und Weise bewahrt XML-Kommentare etc.

Für mich ist die eigentliche Kopie & Suchen & Ersetzen scheint der perfekte Job für ein Stylesheet. In einem XSLT haben Sie kein Problem überhaupt einfach kopieren alles (einschließlich der Elemente sind Sie Probleme mit haben) und legen Sie einfach Ihre Daten, wo es erforderlich ist. Sie können den spezifischen Wert Ihrer Daten in über ein XSL-Parameter übergeben oder Sie können das Stylesheet sich dynamisch ändern (wenn Sie als String in Ihrem Groovy Programm enthalten). Diesen XSLT aufrufen Dokument (e) von zu transformieren, in Groovy ist sehr einfach.

Ich gepflasterten schnell die folgenden Groovy Skript zusammen (aber ich habe keine Zweifel, kann es noch einfacher / kompakt geschrieben werden):

import javax.xml.transform.TransformerFactory
import javax.xml.transform.stream.StreamResult
import javax.xml.transform.stream.StreamSource

def xml = """
<?xml version="1.0" encoding="utf-8"?>
<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:FA_Ansoegning:http---ementor-dk-application-2007-06-22-" href="manifest.xsf" solutionVersion="1.0.0.14" productVersion="12.0.0" PIVersion="1.0.0.0" ?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?>
<application:FA_Ansoegning xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:application="http://ementor.dk/application/2007/06/22/"
xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"
xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/200    8-04-14T14:31:48">
    <Mobiltlf></Mobiltlf>
  <E-mail-adresse></E-mail-adresse>
</application:FA_Ansoegning>
""".trim()

def xslt = """
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:param name="mobil" select="'***dummy***'"/>
    <xsl:param name="email" select="'***dummy***'"/>

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

    <xsl:template match="Mobiltlf">
        <xsl:copy>
            <xsl:value-of select="\$mobil"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="E-mail-adresse">
        <xsl:copy>
            <xsl:value-of select="\$email"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
""".trim()

def factory = TransformerFactory.newInstance()
def transformer = factory.newTransformer(new StreamSource(new StringReader(xslt)))

transformer.setParameter('mobil', '1234567890')
transformer.setParameter('email', 'john.doe@foobar.com')

transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(System.out))

Ausführen dieses Skripts erzeugt:

<?xml version="1.0" encoding="UTF-8"?><?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:FA_Ansoegning:http---ementor-dk-application-2007-06-22-" href="manifest.xsf" solutionVersion="1.0.0.14" productVersion="12.0.0" PIVersion="1.0.0.0" ?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?>
<application:FA_Ansoegning xmlns:application="http://ementor.dk/application/2007/06/22/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/200    8-04-14T14:31:48">
    <Mobiltlf>1234567890</Mobiltlf>
  <E-mail-adresse>john.doe@foobar.com</E-mail-adresse>
</application:FA_Ansoegning>

Brilliant! Vielen Dank für Sie Hilfe:)

Das löst mein Problem in eine viel sauberen und einfachen Art und Weise. Es ist am Ende aussehen wie folgt aus:

def rtv = { xmlSource, tagName, newValue ->
    regex = "<$tagName>[^<]*</$tagName>"
    replacement = "<$tagName>${newValue}</$tagName>"
    xmlSource = xmlSource.replaceAll(regex, replacement)
    return xmlSource
}

input = rtv( input, "Mobiltlf", "32165487" )
input = rtv( input, "E-mail-adresse", "bob@email.com" )
println input

Da ich dies unseren Testern für den Einsatz in ihren Test-Tool SoapUI gebe, habe ich versucht, zu „wickeln“ es, um es für sie leichter zu kopieren und einzufügen.

Das ist gut genug für meine Zwecke, aber es wäre perfekt, wenn wir noch einen „Twist“ hinzufügen könnten

Lassen Sie uns sagen, dass die Eingabe dieses in sich hatte ...

<Mobiltlf type="national" anotherattribute="value"></Mobiltlf>

... und wir wollten thos zwei Attribute auch behalten, obwohl wir den Wert ersetzt. Gibt es eine Möglichkeit regexp zu verwenden, für das auch?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top