Reputation: 1060
I want to move a part of an XML file into another node using XSLT. I only want to move everything starting a certain node. It will be best to explain through an example.
This would be the input XML (it's just a sample)
<Messages>
<Message>
<Header>
<Name>Message Content 1</Name>
</Header>
<Info1>
<Description>blabla</Description>
</Info1>
<Info2>
<Name>Test</Name>
<Description>blabla</Description>
</Info2>
... Possible more nodes (with random names)
<Header>
<Name>Message Content Summary</Name>
</Header>
<Info1>
<Total>blablabla</Total>
</Info1>
... Possible more nodes (with random names)
</Message>
</Messages>
I would like to get the following output:
<Messages>
<Message>
<Header>
<Name>Message Content 1</Name>
</Header>
<Info1>
<Description>blabla</Description>
</Info1>
<Info2>
<Name>Test</Name>
<Description>blabla</Description>
</Info2>
... Possible more nodes (with random names)
</Message>
<MessageSummary>
<Header>
<Name>Message Content Summary</Name>
</Header>
<Info1>
<Total>blablabla</Total>
</Info1>
... Possible more nodes (with random names)
</MessageSummary>
</Messages>
So I want to move everything starting from the last occurance of the node "Header" into a seperate node "MessageSummary".
Is there any way I can accomplish this using XSLT 1.0? Any help would be greatly appreciated.
Thanks.
Upvotes: 1
Views: 1567
Reputation: 122364
So when you're at the context of the input Message
element, you want to put any element that has at least one Header
after it into the output Message
and everything else inside MessageSummary
. You can distinguish these two cases as *[following-sibling::Header]
and *[not(following-sibling::Header)]
, so if we start from a standard identity transformation we end up with
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" />
<!-- identity template - copies everything as-is unless overridden -->
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
</xsl:template>
<xsl:template match="Message">
<xsl:copy>
<xsl:apply-templates select="*[following-sibling::Header]" />
</xsl:copy>
<MessageSummary>
<xsl:apply-templates select="*[not(following-sibling::Header)]" />
</MessageSummary>
</xsl:template>
</xsl:stylesheet>
If you have other elements named Message
in the "random names" section you may wish to make this template more specific, e.g.
<xsl:template match="Messages/Message">
so it only catches the elements you really want.
Upvotes: 2