I have the following structure in an XML-file:
<root name="name1">
<layer1 name="name2">
<layer2 attribute="sowhat">
</layer2>
</layer1>
</root>
<root name="name1">
<layer1 name="name2">
<layer2 attribute="justit">
</layer2>
</layer1>
</root>
<root name="name1">
<layer1 name="name2">
<layer2 attribute="yeaha">
</layer2>
</layer1>
</root>
<root name="name2123">
<layer1 name="name2">
<layer2 attribute="itis">
</layer2>
</layer1>
</root>
And I want to get a result that looks like:
<root name="name1">
<layer1 name="name2">
<layer2 attribute="sowhat"></layer2>
<layer2 attribute="justit"></layer2>
<layer2 attribute="yeaha"></layer2>
</layer1>
</root>
<root name="name2123">
<layer1 name="name2">
<layer2 attribute="itis">
</layer2>
</layer1>
</root>
So I want to merge and combine nodes as far as possible. I havent uses XSLT yet, tried it, but I dont get it, not even the general idea. Any other ideas or tools?
Thanks
For what it's worth, here is a way to do this in XSLT 1.0.
outputs
The key feature of XSLT is the ability to express complex transformations in relatively few lines of code. The above transformation is 29 lines of code and you could squeeze it even more.
I think a crash course in XSLT goes beyond the scope of this answer. Besides that, there are countless crash courses in XSLT available all over the Internet.
So what I do is I'll give a general overview of what happens here.
First off, I've defined two classes of elements for your input - those that are merge-able and those that are not. I've defined all elements that have a
@name
attribute to be merge-able.@name
) are copied as they are. The first<xsl:template>
does that (it's the identity template).@name
attribute values along their ancestors.@name
attributes for all elements that have them.concat(@name, '|', ancestor::*[1]/@name, '|', ancestor::*[2]/@name)
).sowhat
isname2|name1||
, this applies for the other<layer2>
in that logical group.@name
, it$myKey
).$myGroup
).$myGroup/*
).There are some assumptions/limitations in my code that might not necessarily align with your input.
@name
and not by some other property.@name
ancestry do not have special attributes, so throwing away every element but the first one in a certain group will not cause loss of data.<layer>
with a@name
inside a<layer>
without a@name
)Reading recommendations