Как напечатать путь для текущего узла XML в Groovy? - PullRequest
0 голосов
/ 12 апреля 2019

Я перебираю XML-файл и хочу напечатать gpath для каждого узла со значением.Я провел день, читая документы Groovy API и пробуя что-то, но кажется, что то, что я считаю простым, не реализовано каким-либо очевидным способом.

Вот некоторый код, показывающий различные вещи, которые вы можете получить изNodeChild.

    import groovy.util.XmlSlurper

    def myXmlString = '''
    <transaction>
        <payment>
            <txID>68246894</txID>
            <customerName>Huey</customerName>
            <accountNo type="Current">15778047</accountNo>
            <txAmount>899</txAmount>
        </payment>
        <receipt>
            <txID>68246895</txID>
            <customerName>Dewey</customerName>
            <accountNo type="Current">16288</accountNo>
            <txAmount>120</txAmount>
        </receipt>
        <payment>
            <txID>68246896</txID>
            <customerName>Louie</customerName>
            <accountNo type="Savings">89257067</accountNo>
            <txAmount>210</txAmount>
        </payment>
        <payment>
            <txID>68246897</txID>
            <customerName>Dewey</customerName>
            <accountNo type="Cheque">123321</accountNo>
            <txAmount>500</txAmount>
        </payment>
    </transaction>
    '''

    def transaction = new XmlSlurper().parseText(myXmlString)

    def nodes = transaction.'*'.depthFirst().findAll { it.name() != '' }

    nodes.each { node -> 
        println node
        println node.getClass()
        println node.text()
        println node.name()
        println node.parent()
        println node.children()
        println node.innerText
        println node.GPath
        println node.getProperties()
        println node.attributes()
        node.iterator().each { println "${it.name()} : ${it}" }
        println node.namespaceURI()
        println node.getProperties().get('body').toString()
        println node.getBody()[0].toString()
        println node.attributes()
    }        

Я нашел сообщение groovy Print path и значение элементов в xml , которое приблизилось к тому, что мне нужно, но не масштабируется для глубоких узлов (см. Выводниже).

Пример кода по ссылке:

    transaction.'**'.inject([]) { acc, val -> 
        def localText = val.localText() 
        acc << val.name()

        if( localText ) {
            println "${acc.join('.')} : ${localText.join(',')}"
            acc = acc.dropRight(1) // or acc = acc[0..-2]
        }
        acc
    }

Вывод примера кода:

    transaction/payment/txID : 68246894
    transaction/payment/customerName : Huey
    transaction/payment/accountNo : 15778047
    transaction/payment/txAmount : 899
    transaction/payment/receipt/txID : 68246895
    transaction/payment/receipt/customerName : Dewey
    transaction/payment/receipt/accountNo : 16288
    transaction/payment/receipt/txAmount : 120
    transaction/payment/receipt/payment/txID : 68246896
    transaction/payment/receipt/payment/customerName : Louie
    transaction/payment/receipt/payment/accountNo : 89257067
    transaction/payment/receipt/payment/txAmount : 210
    transaction/payment/receipt/payment/payment/txID : 68246897
    transaction/payment/receipt/payment/payment/customerName : Dewey
    transaction/payment/receipt/payment/payment/accountNo : 123321
    transaction/payment/receipt/payment/payment/txAmount : 500

Помимо помощи, чтобы понять это правильно, я также хочу понять, почему тамэто не простая функция, такая как node.path или node.gpath, которая выводит абсолютный путь к узлу.

1 Ответ

0 голосов
/ 12 апреля 2019

Вы могли бы сделать такую ​​вещь:

import groovy.util.XmlSlurper
import groovy.util.slurpersupport.GPathResult

def transaction = new XmlSlurper().parseText(myXmlString)

def leaves = transaction.depthFirst().findAll { it.children().size() == 0 }

def path(GPathResult node) {
    def result = [node.name()]
    def pathWalker = [hasNext: { -> node.parent() != node }, next: { -> node = node.parent() }] as Iterator
    (result + pathWalker.collect { it.name() }).reverse().join('/')
}

leaves.each { node -> 
    println "${path(node)} = ${node.text()}"
}        

Что дает вывод:

transaction/payment/txID = 68246894
transaction/payment/customerName = Huey
transaction/payment/accountNo = 15778047
transaction/payment/txAmount = 899
transaction/receipt/txID = 68246895
transaction/receipt/customerName = Dewey
transaction/receipt/accountNo = 16288
transaction/receipt/txAmount = 120
transaction/payment/txID = 68246896
transaction/payment/customerName = Louie
transaction/payment/accountNo = 89257067
transaction/payment/txAmount = 210
transaction/payment/txID = 68246897
transaction/payment/customerName = Dewey
transaction/payment/accountNo = 123321
transaction/payment/txAmount = 500

Не уверен, что это то, что вам нужно, поскольку вы не говорите, почему оно "не масштабируется для глубоких узлов"

...