Groovy: Create a Map with JAX-B Object's specific attributes

后端 未结 2 1694
日久生厌
日久生厌 2020-12-02 00:17

I have a sample LEDES XML file https://codebeautify.org/xmlviewer/cbdc79e7

Generted Ledesxmlebilling21 class using JDK\'s xjc as below and Ledes21.xsd

相关标签:
2条回答
  • 2020-12-02 00:32

    My guess would be that the schema will have a cyclic property. Have a look here perhaps: JAXB Mapping cyclic references to XML

    0 讨论(0)
  • 2020-12-02 00:50

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

    Update:

    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.

    0 讨论(0)
提交回复
热议问题