-1
<CstmrCdtTrfInitn>
    <GrpHdr>
        <MsgId>201805231510</MsgId>
        <CreDtTm>2018-05-23T12:01:14</CreDtTm>
        <NbOfTxs>1</NbOfTxs>
        <CtrlSum>111.00</CtrlSum>
        <InitgPty>
            <Nm>custName</Nm>
            <Id>
                <OrgId>
                    <Othr>
                        <Id>orgNumber</Id>
                        <SchmeNm>
                            <Cd>ABCD</Cd>
                        </SchmeNm>
                    </Othr>
                </OrgId>
            </Id>
        </InitgPty>
    </GrpHdr>
</CstmrCdtTrfInitn>

I have found several examples on how to modify some text in a XML file. But my problem is that there are repetitive nodes, like in the below example where node Id occurs several times. I would like to modify the value orgNumber with something else but I don´t really manage to find correct Id. Any input would be appreciated.

Matheus Lacerda
  • 5,983
  • 11
  • 29
  • 45
ASE
  • 355
  • 2
  • 12
  • 2
    What have you tried so far? We don't want to suggest things that haven't worked for you. – Wai Ha Lee May 24 '18 at 14:01
  • Parse the whole XML tree with your favorite DOM parser and make the change there, then serialize back to text. – bhspencer May 24 '18 at 14:01
  • [When asking a question about a problem caused by your code, you will get much better answers if you provide code people can use to reproduce the problem. Click this comment to find out how to provide what we need to help you.](https://stackoverflow.com/help/mcve) –  May 24 '18 at 15:03
  • Suggesting to use XPath and the DOM API might answer the question in a generic way, but is definitely the wrong approach for ISO 20022 and other massive XML message payloads in general; JAXB or another typed approach is much more recommendable here, all the more so since the ISO 20022 message schemas, in turn, are generated from UML – imhotap May 24 '18 at 15:18

1 Answers1

-1

Your XML looks like an ISO 20022 interbanking/payment message. I've had success using JAXB with ISO 20022 schemas. JAXB (part of J2EE/JEE, or Jakarta EE as it is called now) will give you a Java POJO representation of the XML message which you can then freely construct and otherwise manipulate like any other Java object graph. For example, you would be able to access the content of the (innermost) Id element in your example using Java expressions such as

CstmrCdtTrfInitn myMessage = ...;
String valueOfIdElement =
 myMessage.getGrpHdr().getInitgPty().getId().getOrgId().getId();

For using JAXB, it's required to have XML Schema files (.xsd files) describing your XML data. You will need to generate Java classes from .xsd files using eg. https://github.com/highsource/maven-jaxb2-plugin (from maven) or just the xjc tool which is part of the JAXB reference implementation (from the command line) and then configure JAXB for the schemas you have. You'll generally want to at least configure the Java package namespaces of the generated Java classes.

imhotap
  • 2,275
  • 1
  • 8
  • 16
  • Thank you all for commenting my post. This JAXB sound like something I would need to learn more about but as you can notice I have not done so much programming so I am trying with things where I can at least find some examples on. I have tried in many different way but more or less they are all in this below way which I cannot get to work – ASE May 24 '18 at 17:42
  • NodeList InitgPtyNodeList = doc.getElementsByTagName("InitgPty"); for(int i = 0; i < InitgPtyNodeList.getLength(); i++) { Node InitgPty = InitgPtyNodeList.item(i); if(InitgPty.hasChildNodes()) { NodeList InitgPtyChilds = InitgPty.getFirstChild().getNextSibling().getChildNodes(); – ASE May 24 '18 at 17:46
  • OK, I checked som examples about JAXB and actually I managed to generate all the classes from my xsd. I did it via CMD by typing "...Test\src>xjc -p pain113.jaxb.beans pain113.xsd". Now I have many Java files and as you said I can write somethine like myMessage.getGrpHdr().getInitgPty().getId().getOrgId().getId(); However, now of course another problem occurs. How can I connect these classes to my actual XML? I read something about marshalling and unmarshalling but I don´t understand it completely. This is what I am trying at the moment: – ASE May 24 '18 at 22:03
  • 1
    File file = new File("C:\\Test\\src\\T1.xml"); JAXBContext jaxbContext = JAXBContext.newInstance(); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); pain113.jaxb.beans.Document d = (pain113.jaxb.beans.Document) jaxbUnmarshaller.unmarshal(file); System.out.println(d.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().getNm()); But this just gives me a lot of errors. Any suggestion? – ASE May 24 '18 at 22:03
  • @AmirSejdinovic I suggest you post another SO question with the details (description of your setup and the error message you get) - it's hard to tell not knowing your CLASSPATH setup, your IDE (if any), etc. Congrats for getting this far! – imhotap May 24 '18 at 22:19
  • Not sure how to do this in best way but I will try to explain in detail. I am using Eclipse as a IDE. My workspace contains two packages. The main one (default) where the main-method is located and the new one where I have all these .java files created from the xsd. This one is called "pain113.jaxb.beans" My test file, the XML file I want to parse is located at C:\\Test\\src\\T1.xml. The file is as shown above but with header: – ASE May 24 '18 at 22:36
  • The code looks like this: JAXBContext jaxbContext = JAXBContext.newInstance(); Unmarshaller u = jaxbContext.createUnmarshaller(); pain113.jaxb.beans.Document d = (pain113.jaxb.beans.Document) u.unmarshal(new FileInputStream("C:\\Test\\src\\T1.xml")); – ASE May 24 '18 at 22:37
  • Running this gives me following errors: javax.xml.bind.UnmarshalException: unexpected element (uri:"urn:iso:std:iso:20022:tech:xsd:pain.001.001.03", local:"Document"). Expected elements are (none) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Unknown Source) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Unknown Source) – ASE May 24 '18 at 22:40
  • Not sure if I am on right path but what I would like to do now is to read my T1.xml file by using these .java classes created from the XSD. Something like Document.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().getNm()); – ASE May 24 '18 at 22:44
  • Checkout if https://stackoverflow.com/questions/20586737/javax-xml-bind-unmarshalexception-unexpected-element-expected-elements-are-no#20587298 helps – imhotap May 24 '18 at 22:48
  • ok, thanks. I am gettig some progress. But new questions comes up. I have actualy managed to modify one XML element in my XML file. I did this by using the top level (root) java file created from my XSD, this java file is called Document. This is the code to get() and set() the XML element. – ASE May 27 '18 at 00:14
  • JAXBContext jc = JAXBContext.newInstance("pain113.jaxb.beans"); Unmarshaller u = jc.createUnmarshaller(); JAXBElement doc = (JAXBElement) u.unmarshal(new File("C:\\Test\\src\\T1.xml")); pain113.jaxb.beans.Document newDoc = doc.getValue(); System.out.println("1 = " + newDoc.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().getId().getOrgId().getOthr().iterator().next().getId()); newDoc.getCstmrCdtTrfInitn().getGrpHdr().getInitgPty().getId().getOrgId().getOthr().iterator().next().setId("AmirTesting"); – ASE May 27 '18 at 00:17
  • All my changes are shown in the Console output by this code: marshaller.marshal( newDocOut, System.out ); Question1: Is it possible to instead of redirecting the output to Consle write it to XML file, the same or another one? If yes how? Question2: How do I print alla the XML elements in my XML file which I am not checking or modifying? 90% of the XML file I will not modify so all those elements I would just like to keep as is. But is there a way to just print all those elements? – ASE May 27 '18 at 00:47
  • `marshaller.marshal(newDocOut, new File("ouputfile.xml"));` – imhotap May 27 '18 at 16:28
  • @AmirSejdinovic please mark question as answered – imhotap May 29 '18 at 04:57