Я думаю, что это может сделать то, что вы намереваетесь сделать.Это несколько вдохновлено предложенным решением Дмитрия Хамитова.Я, конечно, скопировал / вставил некоторые из них.
Имейте в виду, что нет смысла делать xpaths для конечных тегов.Поэтому я исключил их из предложенного решения.
Вы должны быть в состоянии скопировать / вставить это в Groovy Step в SoapUI и запустить его как есть.
Я также изменилПример XML, включающий более одного элемента внутри, чтобы проиллюстрировать обработку списка элементов.
Построенный xpath всегда будет возвращать индекс, который по умолчанию будет [1].Это потому, что каждый отдельный узел потенциально является первым элементом в списке.Нет никакого способа узнать, так ли это, без заглядывания в XML или изучения схемы.Это усложнит решение, и вы получите только немного более тонкий путь xpath, который в итоге даст тот же результат.
Чтобы получить файл CSV, вы можете настроить printStack.В настоящее время он просто выводит в журнал.
def input = """
<Vehicles>
<ns1:Cars xmlns:ns1="asdf" xmlns:ns2="ieurieur">
<ns2:Car>
<Prius/>
</ns2:Car>
<ns2:Car>
<Ka/>
</ns2:Car>
</ns1:Cars>
<Boat>
<Yacht/>
</Boat>
<Bicycle/>
</Vehicles>
"""
def root = new XmlParser().parseText(input)
java.util.Stack nodeStack = new java.util.Stack<String>()
traverse(root,1,nodeStack)
return
void traverse(Node node, Integer index, java.util.Stack stack) {
def nsposition = new Integer(node.name().toString().indexOf("}"))
nsposition++
def nodename = node.name().toString().substring(nsposition)
stack.push(nodename + "[" + index + "]")
def path = buildPath(stack)
printStack(nodename,stack)
def children = node.children()
def childCount = new java.util.HashMap<String,Integer>()
if (children) {
children.each {
def count = getIndex(it.name(),childCount)
childCount.put(it.name(),count)
traverse(it,count,stack)
}
}
stack.pop()
}
void printStack(def nodename, def stack) {
def indentation = ""
for (def x=0; x<stack.size(); x++) {
indentation += " "
}
def path = ""
for (def element : stack.elements()) {
path += "/${element}"
}
log.info "${indentation}<${nodename}>|${path}"
}
Integer getIndex(def name, def childCount) {
if (childCount.containsKey(name)) {
return childCount.get(name) + 1
}
else {
return 1
}
}
String buildPath(def stack) {
def result = ""
for (def element : stack.elements()) {
result += "/" + element
}
return result
}
Пример вывода из журнала:
Tue May 21 15:59:13 CEST 2019: INFO: <Vehicles>|/Vehicles[1]
Tue May 21 15:59:13 CEST 2019: INFO: <Cars>|/Vehicles[1]/Cars[1]
Tue May 21 15:59:13 CEST 2019: INFO: <Car>|/Vehicles[1]/Cars[1]/Car[1]
Tue May 21 15:59:13 CEST 2019: INFO: <Prius>|/Vehicles[1]/Cars[1]/Car[1]/Prius[1]
Tue May 21 15:59:13 CEST 2019: INFO: <Car>|/Vehicles[1]/Cars[1]/Car[2]
Tue May 21 15:59:13 CEST 2019: INFO: <Ka>|/Vehicles[1]/Cars[1]/Car[2]/Ka[1]
Tue May 21 15:59:13 CEST 2019: INFO: <Boat>|/Vehicles[1]/Boat[1]
Tue May 21 15:59:13 CEST 2019: INFO: <Yacht>|/Vehicles[1]/Boat[1]/Yacht[1]
Tue May 21 15:59:13 CEST 2019: INFO: <Bicycle>|/Vehicles[1]/Bicycle[1]