I have a sample LEDES XML file https://codebeautify.org/xmlviewer/cbdc79e7
Generted Ledesxmlebilling21 class using JDK\'s xjc
as below and Ledes21.xsd
My guess would be that the schema will have a cyclic property. Have a look here perhaps: JAXB Mapping cyclic references to XML
I believe what you want is to recursively iterate over groovy properties.
I skip over the JAX-B parsing since you have that solved already, and use my own classes. The groovy code is not idiomatic and could be shortened
class LedesStatementTest extends GroovyTestCase {
// Recursive function adding file_item_nbr to given list
def extractFileItemNbr(input, List<Integer> extracted) {
input.properties.each { prop, val ->
if (prop in ["metaClass", "class"]) return
if (prop == 'file_item_nbr') {
// println(" $prop : $val")
extracted << val
} else {
extractFileItemNbr(val, extracted)
}
}
}
// deal with list fields
def extractFileItemNbr(List input, List<Integer> extracted) {
input.each {
extractFileItemNbr(it, extracted)
}
}
void testExtract() {
List<LedesInvoice> invoices = [new LedesInvoice([inv_id: 'Invoice 31',
file_item_nbr: 10,
statement: new LedesStatement([file_item_nbr: 11]),
summary: [new LedesTaxSummary([file_item_nbr: 12]), new LedesTaxSummary([file_item_nbr: 13])]]),
new LedesInvoice([inv_id: 'Invoice 32',
file_item_nbr: 50,
statement: new LedesStatement([file_item_nbr: 51]),
summary: [new LedesTaxSummary([file_item_nbr: 52]),
new LedesTaxSummary([file_item_nbr: 53])]])
]
Map<String, List<Integer>> extracted = [:]
for (LedesInvoice invoice : invoices) {
def accuList = []
extractFileItemNbr(invoice, accuList)
extracted.put(invoice.inv_id, accuList)
}
println(extracted)
}
// data classes, similar to Ledes XML, simplified
static class LedesInvoice {
String inv_id;
int file_item_nbr;
LedesStatement statement;
List<LedesTaxSummary> summary;
}
static class LedesStatement {
int file_item_nbr;
}
static class LedesTaxSummary {
int file_item_nbr;
}
}
Output:
[Invoice 31:[12, 13, 11, 10], Invoice 32:[52, 53, 51, 50]]
In case of cycles, don't just pass around a List<Integer> extracted
of extracted ints, but also a a Set of visited inputs, and in each extract method check if the given input is already in the list.