Getting Element Name via XML Readers

I’m working on parsing a complicated XML document that shares many of the same child nodes between many different parent nodes. For example:


<root>
  <parent1>
    <child1/>
    <child2/>
    <child3/>
  </parent1>
  <parent2>
    <child1/>
    <child2/>
    <child3/>
  </parent2>
</root>

My proposed solution to this is to use the XMLXPathReader to grab each of the parent nodes, such as the following:

<Context xpath=“parent1|parent2” outPort=“0” …/>

This works great, but the problem is that I cannot seem to find a way to get the name of the node that it’s referencing. I’d like to be able to know if it got the metadata from parent1, parent2, etc, in case they need to be parsed differently.

Is this possible, or is there a better means for doing this? If needed, I can emulate includes with parameters and do something like:


<root>
  <parent1>
    ${CHILDREN}
  </parent1>
  <parent2>
    ${CHILDREN}
  </parent2>
</root>

But I was hoping there was a better way.

I tried using the Autofill fields but they didn’t seem to return the results I need. I think this would be an excellent feature if there’s no means to do this currently.

Thank you for your help.

Hello Mike,

If I understand what you want, you can use the following mapping in XMLExtract:


<Mappings>
<Mapping element="parent1">
<Mapping element="child1" outPort="0" />
<Mapping element="child2" outPort="1" />
<Mapping element="child3" outPort="2" />
</Mapping>
<Mapping element="parent2">
<Mapping element="child1" outPort="0" />
<Mapping element="child2" outPort="1" />
<Mapping element="child3" outPort="2" />
</Mapping>
</Mappings>

By specifying parent# elements you are saying that you want to get child elements from the specified parent only. Once you get any child# value, you can send each child# to the same output port.
(You do not need to send each mapped element to an output port, this way - by mapping without any output port - you can specify where the child elements are nested.)

Is this what you wanted to get? (I suppose child elements will not be empty.)

Best regards,

Tomas Waller

Should you wanted to parse child of different parent in a different way, you can create for each child separate output port. This way they would be sent to six ports instead of three.

Regards,

Tomas Waller

Thanks for the reply.

Below is an example of the problem:


<root>
  <FirstParent>
    <child>Value</child>
    <anotherChild>Value</anotherChild>
  </FirstParent>
  <SecondParent>
    <child>Value</child>
    <anotherChild>Value</anotherChild>
  </SecondParent>
  <ThirdParent>
    <child>Value</child>
    <anotherChild>Value</anotherChild>
  </ThirdParent>
  <FourthParent>
    <child>Value</child>
    <anotherChild>Value</anotherChild>
  </FourthParent>
</root>

We have literally around 100 parent nodes that share the exact same child nodes. The parent node determines how we need to parse the data. Therefore, I was hoping that there was a way to send all the child nodes to the same output ports, but have the system tell me what parent node it came from. This way, we can do the necessary processing without having ports equal to: numChildren x numParents (there’s potentially 100s of child nodes as well, so I don’t want 100 parent nodes x 100 child nodes = 10,000 output ports…I’d much rather have 100 output ports).

Thanks,
Mike

Hello Mike,

I processed the file you wanted with four parents as an example:


<root>
  <parent1>
    <child1>1child1</child1>
    <child2>1child2</child2>
    <child3>1child3</child3>
  </parent1>
  <parent2>
    <child1>2child1</child1>
    <child2>2child2</child2>
    <child3>2child3</child3>
  </parent2>
  <parent3>
    <child1>3child1</child1>
    <child2>3child2</child2>
    <child3>3child3</child3>
  </parent3>
  <parent4>
    <child1>4child1</child1>
    <child2>4child2</child2>
    <child3>4child3</child3>
  </parent4>
</root>

I read it with XMLExtract with two edges. One served to get information about parents. The other served to get information about both parents and children.

All children went to the same edge. Thus, the edge for parents consisted of 4 fields. The edge for children consisted of 3 fields for children plus 4 fields for parents.

In your case, you would have 100 fields for parents and 100 fields for children. (100 fields one edge, 200 the other).

You need to create a sequence. Step 1, initial value 1, any cache.

Your mapping will be something like the following:


<Mappings>
<Mapping element="parent1" outPort="1" sequenceId="Sequence0" sequenceField="par1">
<Mapping element="child1" outPort="0" parentKey="par1" generatedKey="par1"/>
<Mapping element="child2" outPort="0" parentKey="par1" generatedKey="par1"/>
<Mapping element="child3" outPort="0" parentKey="par1" generatedKey="par1"/>
</Mapping>
<Mapping element="parent2" outPort="1" sequenceId="Sequence0" sequenceField="par2">
<Mapping element="child1" outPort="0" parentKey="par2" generatedKey="par2"/>
<Mapping element="child2" outPort="0" parentKey="par2" generatedKey="par2"/>
<Mapping element="child3" outPort="0" parentKey="par2" generatedKey="par2"/>
</Mapping>
<Mapping element="parent3" outPort="1" sequenceId="Sequence0" sequenceField="par3">
<Mapping element="child1" outPort="0" parentKey="par3" generatedKey="par3"/>
<Mapping element="child2" outPort="0" parentKey="par3" generatedKey="par3"/>
<Mapping element="child3" outPort="0" parentKey="par3" generatedKey="par3"/>
</Mapping>
<Mapping element="parent4" outPort="1" sequenceId="Sequence0" sequenceField="par4">
<Mapping element="child1" outPort="0" parentKey="par4" generatedKey="par4"/>
<Mapping element="child2" outPort="0" parentKey="par4" generatedKey="par4"/>
<Mapping element="child3" outPort="0" parentKey="par4" generatedKey="par4"/>
</Mapping>
</Mappings>

Here “par#” are the fields representing parents, whereas “child#” represent children. All the parent fields can be string fields.

For each child only one of these “par#” will be filled by a value. The others will be empty.

This way you can distinguish the children of different parents.

Does this solution satisfy you?

Best regards,

Tomas Waller

That may be sufficient; thanks for your help :slight_smile: