ATL transformation rules not matching nested BPMN2 elements - eclipse-emf-ecore

I am writing an ATL translation from BPMN2 to another model. The problem is that the code does not detect any nested element.
I have posted the atl code and my input here at: https://github.com/behnaaz/BPMN2ATL.git
You can see from the output that the only executed rule is def2mod which has created a Reo module element in the output.
If I remove the first level element in the input bpmn file then the rule mapProcess is kicked in.
Also in the logs the command BPMN20!Process.allInstances() which should give a list of all the Processes only works in the mapProcess rule.
I think there is some issue with parsing my bpmn model. Help much appreciated!
=== ATL CODE ====
-- #path BPMN20=/atttl/BPMN2/BPMN20.ecore
create OUT: reo from IN: BPMN20;
rule def2mod {
from
b: BPMN20!Definitions
to
m: reo!Module
do {
b.debug('definition to module > ' + BPMN20!Process.allInstances());
}
}
rule mapProcess {
from
proc: BPMN20!Process
to
conn: reo!Connector
do {
proc.debug('process to connector ' + proc.name + proc.flowElements);
proc.debug( BPMN20!Process.allInstances());
}
}
=== BPMN input ===
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:Definitions xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL-XMI">
<bpmn2:Process id="bpmnid-80c796ae-c11d-42d8-92ae-1d88bab84536" name="Process" isClosed="false" processType="None" xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL-XMI">
<bpmn2:serviceTask id="bpmnid-11047880-09d8-4147-8382-523145eeb8b6" name="Task 1"/>
<bpmn2:serviceTask id="bpmnid-2f925dd9-4ec8-45b7-936c-0c14597319a9" name="Task 2"/>
<bpmn2:serviceTask id="bpmnid-21a0fc44-3c02-4a00-9b6e-aa6c058992d3" name="Task 3"/>
<bpmn2:startEvent id="bpmnid-196c656e-baa2-4306-809b-56ba006057b9" name="Start Event"/>
<bpmn2:endEvent id="bpmnid-5cfcf354-ba3f-4b13-a5bf-bdf27ca70acc" name="End Event"/>
<bpmn2:sequenceFlow id="bpmnid-be0a37d4-8054-4367-82ae-b43430d5fc6f" name="Sequence Flow0" sourceRef="bpmnid-11047880-09d8-4147-8382-523145eeb8b6" targetRef="bpmnid-2f925dd9-4ec8-45b7-936c-0c14597319a9"/>
<bpmn2:sequenceFlow id="bpmnid-01d687a3-66ee-40d7-9e17-97aa5724eef7" name="Sequence Flow" sourceRef="bpmnid-196c656e-baa2-4306-809b-56ba006057b9" targetRef="bpmnid-11047880-09d8-4147-8382-523145eeb8b6"/>
<bpmn2:sequenceFlow id="bpmnid-b687d3ec-b6d7-480a-a1e1-57fbe220e579" name="Sequence Flow2" sourceRef="bpmnid-21a0fc44-3c02-4a00-9b6e-aa6c058992d3" targetRef="bpmnid-5cfcf354-ba3f-4b13-a5bf-bdf27ca70acc"/>
<bpmn2:sequenceFlow id="bpmnid-4596a8fb-f1dc-46b3-bc28-9a2e11c26f96" name="Sequence Flow1" sourceRef="bpmnid-2f925dd9-4ec8-45b7-936c-0c14597319a9" targetRef="bpmnid-21a0fc44-3c02-4a00-9b6e-aa6c058992d3"/>
</bpmn2:Process>
</bpmn2:Definitions>

The problem seems not to lie with the ATL transformation but with the input model. It seems like it's not conform to your metamodel.
E.g. Definitions has a relation "rootElements" to Process. This should in the XMI model look like this:
<bpmn2:Definitions
xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL-XMI">
<rootElements xsi:type="bpmn2:Process" id="bpmnid-80c796ae-c11d-42d8-92ae-1d88bab84536" />
</bpmn2:Definitions>
To quickly get a conform model you can right-click the Definitions element in your ecore metamodel and choose "Create Dynamic Instance". You can then model a quick sample and run your transformation again. I quickly tried it and got following output
<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:reo="http://www.cwi.nl/reo">
<reo:Module/>
<reo:Connector/>
</xmi:XMI>

Related

how to reuse the xpr file in Mule 4

In my case, I'm doing a migration from Mule 3 to Mule 4.
This flow, which includes transformers like DOM to XML, XML to DOM, and an expression component, needs to be migrated.
In Mule 4, I want to reuse the xrp file.
My flow for XML payload transform uses an XPR file by the expression component in Mule 3.
<flow name="rate-dtostepFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/dtostep" allowedMethods="POST" doc:name="HTTP"/>
<mulexml:xml-to-dom-transformer returnClass="org.dom4j.Document" doc:name="XML to DOM"/>
<set-variable variableName="domPayload" value="#[payload]" doc:name="set domPayload "/>
<expression-component file="xpr/responseStubCannasure.xpr" doc:name="Expression"/>
<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
</flow>
Input XML: https://github.com/Manikandan99/rate-dtostep/blob/master/request.xml
Output XML: https://github.com/Manikandan99/rate-dtostep/blob/master/response.xml
my MULE 3 application : https://github.com/Manikandan99/rate-dtostep/tree/master/rate-dtostep
ResponseStubcannsure xpr file:
import org.dom4j.*;
import java.util.*;
import java.util.logging.Logger;
Logger logger = Logger.getLogger("");
dtoCoverageStepsNodes = flowVars.domPayload.selectNodes("//DTOCoverage[#Status=\'Active\']/DTOSteps");
for (Node node : dtoCoverageStepsNodes){
//logger.info("inside: detach");
node.detach();
}
dtoCoverageNodes = flowVars.domPayload.selectNodes("//DTOCoverage[#Status=\'Active\']");
int i = 500;
for (Node node : dtoCoverageNodes){
//node.detach();
//logger.info("inside: assign prem");
node.addAttribute("FullTermAmt", Integer.toString(i));
node.addElement("DTOSteps");
stepNode = node.selectSingleNode("DTOSteps");
stepNode.addElement("DTOStep")
.addAttribute("Order","1")
.addAttribute("Name","Final Premium")
.addAttribute("Desc","Final Premium Desc")
.addAttribute("Operation","=")
.addAttribute("Factor",Integer.toString(i))
.addAttribute("Value",Integer.toString(i));
i+=1;
}
The xpr file transform the xml payload in the following ways:
updated the value of the DTOStep node.
The attribute value of DTOStep is autoincremented from 500 each time.
Please assist me.
You need to migrate the complete flow to Mule 4. The file responseStubCannasure.xpr is just a script in MEL (Mule 3 expression language). The extension is irrelevant, it could have been anything. MEL is very similar to Java so you could reuse the logic by encapsulating it into a Java class. You will need to add to the Java code the conversion to DOM4J from the input XML because Mule 4 doesn't support it. Probably is slightly easier to migrate the MEL script to a Groovy script because the basic syntax is very similar and both support scripts. Migrating to Java is just taking the additional steps of encapsulating the script into a method of a class and defining explicitly the types for variables.
Alternatively you could just delete the last 4 operations of the flow and replace them with a DataWeave transformation. Using a recursive function to navigate the keys and value recursively, using a condition to check if we are in the element DTOCoverage, with attribute Status == "Active" and then replace the nested element with the DTOSteps/DTOStep combination. Which is what your script does.
Example:
%dw 2.0
output application/xml
var startingValue=500
fun transformSteps(x, index)=
x filterObject ($$ as String != "DTOSteps") ++
{
DTOSteps: DTOStep #(Order:1, Factor: index + startingValue, Value: index + startingValue, Name:"Final Premiun", Operation:"=", Desc: "Final Premium Desc"): null
}
fun transformCoverage(x, index)=
{
val: x match {
case is Object -> x mapObject
if ($$ as String == "DTOCoverage" and $$.#Status == "Active")
{
DTOCoverage #(( $$.# - "FullTermAmt" ), FullTermAmt: $$$ + startingValue):
transformSteps($, index)
}
else
(($$): transformCoverage($, index+1))
else -> $
},
index: index
}
---
transformCoverage(payload,1).val
This solution doesn't completely resolve the Value and Factor (why two attributes with the same value?) sequential increase. You may need to do an additional transformation, or use Groovy or Java code to renumber them.

UDF/User defined function libreoffice basic with built-in help/tip

I did a function in LibreOffice calc. It works, but I would like to have a conext help/tip capability, like the built in LibreOffice functions.
Example: when I type "=besselk(" it appaears a tip BESSELK(X; N). Using the function wizard a function and arguments description does also appear.
Besselk
besselk
Let's say I have a function to calculte a rectangle area
function arearect(a, b)
arearect = a * b
end function
I would like to have something like this:
function arearect(a, b)
FUNCTION DESCRIPTION "Compute rectangle area"
ARGUMENT DESCRIPTION "base length"
ARGUMENT DESCRIPTION "height"
arearect = a * b
end function
so, when I type "=arearect(" the argument description would appear and all descriptors would appear on Function Wizard.
thanks
Create the user-defined function as a Spreadsheet Add-In. Then enter the help text in the Description node in the .xcu file that defines the add-in.
For example, I created a function called REVERSE. Here is my CalcAddIns.xcu file:
<?xml version="1.0" encoding="UTF-8"?>
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
oor:name="CalcAddIns" oor:package="org.openoffice.Office">
<node oor:name="AddInInfo">
<node oor:name="name.JimK.ReverseStringImpl" oor:op="replace">
<node oor:name="AddInFunctions">
<node oor:name="reverse" oor:op="replace">
<prop oor:name="DisplayName"><value xml:lang="en">reverse</value></prop>
<prop oor:name="Description">
<value xml:lang="en">Flips a string backwards. For example "apple" becomes "elppa".</value>
</prop>
<prop oor:name="Category"><value>Add-In</value></prop>
<!-- This won't help, because there is no reverse() in Excel. -->
<prop oor:name="CompatibilityName"><value xml:lang="en">reverse</value></prop>
<node oor:name="Parameters">
<node oor:name="s" oor:op="replace">
<prop oor:name="DisplayName"><value xml:lang="en">s</value></prop>
<prop oor:name="Description"><value xml:lang="en">The string to reverse.</value></prop>
</node>
</node>
</node>
</node>
</node>
</node>
</oor:component-data>
An Add-In also requires some other files. Here is my XCalcFunctions.idl:
#include <com/sun/star/uno/XInterface.idl>
module name { module JimK { module CalcFunctions {
interface XCalcFunctions
{
string reverse( [in] string s );
};
}; }; };
The actual implementation was simple. I used python:
def reverseString(inString):
s = unicode(inString)
# This is extended slice syntax [begin:end:step]. With a step of -1,
# it will traverse the string elements in descending order.
return s[::-1]
The result:
EDIT:
There is another piece in Components.py for my extension:
class StringReverserAddIn(unohelper.Base, XCalcFunctions):
def __init__(self, ctx):
self.ctx = ctx
#staticmethod
def factory(ctx):
return StringReverserAddIn(ctx)
def reverse(self, inString):
from lingt.app.calcfunctions import reverseString
return reverseString(inString)
g_ImplementationHelper.addImplementation(
StringReverserAddIn.factory,
"name.JimK.LinguisticTools.ReverseStringImpl",
("com.sun.star.sheet.AddIn",),)
The file is declared in manifest.xml:
<!--- The Python code -->
<manifest:file-entry
manifest:full-path="Components.py"
manifest:media-type="application/vnd.sun.star.uno-component;type=Python"/>
The complete extension: https://extensions.libreoffice.org/extensions/lingtools.

How to extract individual/child nodes from a KML file in VisualBasic?

I need to be able to extract individual nodes from this file into variables for further manipulation. I'm writing to the console to see what information is being pulled, but I am struggling to pull the name or description.
I can successfully print the entire file. I've tried getting individual nodes using placemark.<name>.Value and placemark.Element("name").Value, the second of which throws a NullReferenceException. Any ideas on how to be able to pull out the name and description in this instance?
Imports System.Xml
Imports System.Xml.Linq 'Visual Studio 2015 tells me this isn't needed
Imports System.Core 'Visual Studio 2015 tells me this isn't needed
Dim file As XDocument = XDocument.Load(filePath)
Dim placemarks As IEnumerable(Of XElement) = From test In file.Root.Elements()
For Each placemark As XElement In placemarks
Console.WriteLine(placemark) 'This works
Console.WriteLine(placemark.<name>.Value) 'This prints an empty line
Console.WriteLine(placemark.Element("description").Value) 'This throws a NullReferenceException
Next
This is the structure
<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://www.opengis.net/kml/2.2'>
<Document>
<name>Untitled layer</name>
<Placemark>
<name>Name 1</name>
<description>Description 1</description>
<ExtendedData>
<Data name='Test data one'>
<value>Test data 1</value>
</Data>
</ExtendedData>
<Point>
<coordinates>34725567547</coordinates>
</Point>
</Placemark>
<Placemark>
<name>Name 2</name>
<description>Description 2</description>
<ExtendedData>
<Data name='Test data two'>
<value>Test data 2</value>
</Data>
</ExtendedData>
<Point>
<coordinates>056795763767</coordinates>
</Point>
</Placemark>
If I have understood you correctly, you are trying to fetch the name & description present inside the PlaceMark node. But, since you are only fetching Root.Elements() your query will only fetch the complete XML starting from your root node.
You need to find the Descendants of PlaceMark node because you need to fetch the name & description inside it. Also, since the root node kml consists of namespace you need to specify that as well.
Here is the code:-
Dim ns As XNamespace = "http://www.opengis.net/kml/2.2"
Dim placeMarks = From test In file.Root.Element(ns + "Document")
.Descendants(ns + "Placemark") Select test
For Each pm In placeMarks
Console.WriteLine("Name: {0}", pm.Element(ns + "name").Value)
Console.WriteLine("Description: {0}", pm.Element(ns + "description").Value)
Console.WriteLine()
Next
I am getting following output:-

The ':' character, hexadecimal value 0x3A, cannot be included in a name

I saw this question already, but I didnt see an answer..
So I get this error:
The ':' character, hexadecimal value 0x3A, cannot be included in a name.
On this code:
XDocument XMLFeed = XDocument.Load("http://feeds.foxnews.com/foxnews/most-popular?format=xml");
XNamespace content = "http://purl.org/rss/1.0/modules/content/";
var feeds = from feed in XMLFeed.Descendants("item")
select new
{
Title = feed.Element("title").Value,
Link = feed.Element("link").Value,
pubDate = feed.Element("pubDate").Value,
Description = feed.Element("description").Value,
MediaContent = feed.Element(content + "encoded")
};
foreach (var f in feeds.Reverse())
{
....
}
An item looks like that:
<rss>
<channel>
....items....
<item>
<title>Pentagon confirms plan to create new spy agency</title>
<link>http://feeds.foxnews.com/~r/foxnews/most-popular/~3/lVUZwCdjVsc/</link>
<category>politics</category>
<dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/" />
<pubDate>Tue, 24 Apr 2012 12:44:51 PDT</pubDate>
<guid isPermaLink="false">http://www.foxnews.com/politics/2012/04/24/pentagon-confirms-plan-to-create-new-spy-agency/</guid>
<content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[|http://global.fncstatic.com/static/managed/img/Politics/panetta_hearing_030712.jpg<img src="http://feeds.feedburner.com/~r/foxnews/most-popular/~4/lVUZwCdjVsc" height="1" width="1"/>]]></content:encoded>
<description>The Pentagon confirmed Tuesday that it is carving out a brand new spy agency expected to include several hundred officers focused on intelligence gathering around the world.&amp;#160;</description>
<dc:date xmlns:dc="http://purl.org/dc/elements/1.1/">2012-04-4T19:44:51Z</dc:date>
<feedburner:origLink>http://www.foxnews.com/politics/2012/04/24/pentagon-confirms-plan-to-create-new-spy-agency/</feedburner:origLink>
</item>
....items....
</channel>
</rss>
All I want is to get the "http://global.fncstatic.com/static/managed/img/Politics/panetta_hearing_030712.jpg", and before that check if content:encoded exists..
Thanks.
EDIT:
I've found a sample that I can show and edit the code that tries to handle it..
EDIT2:
I've done it in the ugly way:
text.Replace("content:encoded", "contentt").Replace("xmlns:content=\"http://purl.org/rss/1.0/modules/content/\"","");
and then get the element in the normal way:
MediaContent = feed.Element("contentt").Value
The following code
static void Main(string[] args)
{
var XMLFeed = XDocument.Parse(
#"<rss>
<channel>
....items....
<item>
<title>Pentagon confirms plan to create new spy agency</title>
<link>http://feeds.foxnews.com/~r/foxnews/most-popular/~3/lVUZwCdjVsc/</link>
<category>politics</category>
<dc:creator xmlns:dc='http://purl.org/dc/elements/1.1/' />
<pubDate>Tue, 24 Apr 2012 12:44:51 PDT</pubDate>
<guid isPermaLink='false'>http://www.foxnews.com/politics/2012/04/24/pentagon-confirms-plan-to-create-new-spy-agency/</guid>
<content:encoded xmlns:content='http://purl.org/rss/1.0/modules/content/'><![CDATA[|http://global.fncstatic.com/static/managed/img/Politics/panetta_hearing_030712.jpg<img src='http://feeds.feedburner.com/~r/foxnews/most-popular/~4/lVUZwCdjVsc' height='1' width='1'/>]]></content:encoded>
<description>The Pentagon confirmed Tuesday that it is carving out a brand new spy agency expected to include several hundred officers focused on intelligence gathering around the world.&amp;#160;</description>
<dc:date xmlns:dc='http://purl.org/dc/elements/1.1/'>2012-04-4T19:44:51Z</dc:date>
<!-- <feedburner:origLink>http://www.foxnews.com/politics/2012/04/24/pentagon-confirms-plan-to-create-new-spy-agency/</feedburner:origLink> -->
</item>
....items....
</channel>
</rss>");
XNamespace contentNs = "http://purl.org/rss/1.0/modules/content/";
var feeds = from feed in XMLFeed.Descendants("item")
select new
{
Title = (string)feed.Element("title"),
Link = (string)feed.Element("link"),
pubDate = (string)feed.Element("pubDate"),
Description = (string)feed.Element("description"),
MediaContent = GetMediaContent((string)feed.Element(contentNs + "encoded"))
};
foreach(var item in feeds)
{
Console.WriteLine(item);
}
}
private static string GetMediaContent(string content)
{
int imgStartPos = content.IndexOf("<img");
if(imgStartPos > 0)
{
int startPos = content[0] == '|' ? 1 : 0;
return content.Substring(startPos, imgStartPos - startPos);
}
return string.Empty;
}
results in:
{ Title = Pentagon confirms plan to create new spy agency, Link = http://feeds.f
oxnews.com/~r/foxnews/most-popular/~3/lVUZwCdjVsc/, pubDate = Tue, 24 Apr 2012 1
2:44:51 PDT, Description = The Pentagon confirmed Tuesday that it is carving out
a brand new spy agency expected to include several hundred officers focused on
intelligence gathering around the world. , MediaContent = http://global
.fncstatic.com/static/managed/img/Politics/panetta_hearing_030712.jpg }
Press any key to continue . . .
A few points:
You never want to treat Xml as text - in your case you removed the namespace declaration but actually if the namespace was declared inline (i.e. without binding to the prefix) or a different prefix would be defined your code would not work even though semantically both documents would be equivalent
Unless you know what's inside CDATA and how to treat it you always want to treat is as text. If you know it's something else you can treat it differently after parsing - see my elaborate on CDATA below for more details
To avoid NullReferenceExceptions if the element is missing I used explicit conversion operator (string) instead of invoking .Value
the Xml you posted was not a valid xml - there was missing namespace Uri for feedburner prefix
This is no longer related to the problem but may be helpful for some folks so I am leaving it
As far as the contents of the encode element is considered it is inside CDATA section. What's inside CDATA section is not an Xml but plain text. CDATA is usually used to not have to encode '<', '>', '&' characters (without CDATA they would have to be encoded as < > and & to not break the Xml document itself) but the Xml processor treat characters in the CDATA as if they were encoded (or to be more correct in encodes them). The CDATA is convenient if you want to embed html because textually the embedded content looks like the original yet it won't break your xml if the html is not a well-formed Xml. Since the CDATA content is not an Xml but text it is not possible to treat it as Xml. You will probably need to treat is as text and use for instance regular expressions. If you know it is a valid Xml you can load the contents to an XElement again and process it. In your case you have got mixed content so it is not easy to do unless you use a little dirty hack. Everything would be easy if you have just one top level element instead of mixed content. The hack is to add the element to avoid all the hassle. Inside the foreach look you can do something like this:
var mediaContentXml = XElement.Parse("<content>" + (string)item.MediaContent + "</content>");
Console.WriteLine((string)mediaContentXml.Element("img").Attribute("src"));
Again it's not pretty and it is a hack but it will work if the content of the encoded element is valid Xml. The more correct way of doing this is to us XmlReader with ConformanceLevel set to Fragment and recognize all kinds of nodes appropriately to create a corresponding Linq to Xml node.
You should use XNamespace:
XNamespace content = "...";
// later in your code ...
MediaContent = feed.Element(content + "encoded")
See more details here.
(Of course, you the string to be assigned to content is the same as in xmlns:content="...").

vb.Net: How can I read a large XML file quickly?

I am trying to read this XML document.
An excerpt:
<datafile xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="wiitdb.xsd">
<WiiTDB version="20100217113738" games="2368"/>
<game name="Help Wanted: 50 Wacky Jobs (DEMO) (USA) (EN)">
<id>DHKE18</id>
<type/>
<region>NTSC-U</region>
<languages>EN</languages>
<locale lang="EN">
<title>Help Wanted: 50 Wacky Jobs (DEMO)</title>
<synopsis/>
</locale>
<developer>HUDSON SOFT CO., LTD.</developer>
<publisher>Hudson Entertainment, Inc.</publisher>
<date year="2009" month="" day=""/>
<genre>party</genre>
<rating type="ESRB" value="E10+">
<descriptor>comic mischief</descriptor>
<descriptor>mild cartoon violence</descriptor>
<descriptor>mild suggestive themes</descriptor>
</rating>
<wi-fi players="0"/>
<input players="2">
<control type="wiimote" required="true"/>
<control type="nunchuk" required="true"/>
</input>
<rom version="" name="Help Wanted: 50 Wacky Jobs (DEMO) (USA) (EN).iso" size="4699979776"/>
</game>
So far I have this:
Dim doc as XPathDocument
Dim nav as XPathNavigator
Dim iter as XPathNodeIterator
Dim lstNav As XPathNavigator
Dim iterNews As XPathNodeIterator
doc = New XPathDocument("wiitdb.xml")
nav = doc.CreateNavigator
iter = nav.Select("/WiiTDB/game") 'Your node name goes here
'Loop through the records in that node
While iter.MoveNext
'Get the data we need from the node
lstNav = iter.Current
iterNews = lstNav.SelectDescendants(XPathNodeType.Element, False)
'Loop through the child nodes
txtOutput.Text = txtOutput.Text & vbNewLine & iterNews.Current.Name & ": " & iterNews.Current.Value
End While
It just skips the "While iter.MoveNext" part of the code. I tries it with a simple XML file, and it works fine.
I think your XPath query is off. WiiTDB is a closed node, so you need to look for /datafile/game or //game.
Use the System.Xml.Serialization namespace instead: create a dedicated, serializable class to hold the data you wish to load and define shared serialize / deserialize functions with strongly typed arguments to do the work for you.
As the structure of the new classes will closely follow that of your XML data, there should be no confusion as to which data is located where within a run time instance.
See my answer here for an idea of how to create a class from an example XML file.