Perl XML, find matching condition and grep lines and put the lines somewhere else

Hi,

my xml files looks something like this

<Instance Name="New York">
      <Description></Description>
      <Instance Name="A">
        <Description></Description>
        <PropertyValue Key="false" Name="Building A" />
      </Instance>
      <Instance Name="B">
        <Description></Description>
        <PropertyValue Key="false" Name="Building B" />
      </Instance>
      <PropertyValue Key="false" Name="random" />
      <PropertyValue Key="false" Name="blabla" />
      <PropertyValue Key="false" Name="blabla2" />
    </Instance>

I need to grep all the lines between </Instance> and </Instance> {the 3 proeprty values, there cna be 4 or more, and place them on top between </Description> and <Instance, so it becomes like this

<Instance Name="New York">
<Description></Description>
<PropertyValue Key="false" Name="random" />
<PropertyValue Key="false" Name="blabla" />
<PropertyValue Key="false" Name="blabla2" />
<Instance Name="A">
<Description></Description>
<PropertyValue Key="false" Name="Building A" />
</Instance>
<Instance Name="B">
<Description></Description>
<PropertyValue Key="false" Name="Building B" />
</Instance>
</Instance>
[/CODE]

For the notes, There can be more than 1 parent in file. The Instance name will also be different than New York, but what I need to highlight is the string matching condition. In short, a complete file may look like this

<Instance Name="New York">
      <Description></Description>
      <Instance Name="A">
        <Description></Description>
        <PropertyValue Key="false" Name="Building A" />
      </Instance>
      <Instance Name="B">
        <Description></Description>
        <PropertyValue Key="false" Name="Building B" />
      </Instance>
      <PropertyValue Key="false" Name="random" />
      <PropertyValue Key="false" Name="blabla" />
      <PropertyValue Key="false" Name="blabla2" />
    </Instance>
<Instance Name="Mumbai">
       <Description></Description>
      <Instance Name="C">
         <Description></Description>
         <PropertyValue Key="false" Name="Building C" />
       </Instance>
       <Instance Name="D">
         <Description></Description>
         <PropertyValue Key="false" Name="Building D" />
      </Instance>
      <PropertyValue Key="false" Name="absolute" />
      <PropertyValue Key="false" Name="perl" />
      <PropertyValue Key="false" Name="xml" />
    </Instance>

In which case, the result needs to be like this

<Instance Name="New York">
      <Description></Description>
      <PropertyValue Key="false" Name="random" />
      <PropertyValue Key="false" Name="blabla" />
      <PropertyValue Key="false" Name="blabla2" />
       <Instance Name="A">
        <Description></Description>
        <PropertyValue Key="false" Name="Building A" />
      </Instance>
      <Instance Name="B">
        <Description></Description>
        <PropertyValue Key="false" Name="Building B" />
      </Instance>
    </Instance>
<Instance Name="Mumbai">
       <Description></Description>
      <PropertyValue Key="false" Name="absolute" />
      <PropertyValue Key="false" Name="perl" />
      <PropertyValue Key="false" Name="xml" />
       <Instance Name="C">
         <Description></Description>
         <PropertyValue Key="false" Name="Building C" />
       </Instance>
       <Instance Name="D">
         <Description></Description>
         <PropertyValue Key="false" Name="Building D" />
       </Instance>
    </Instance>

I wonder if this is possible, please help. Thank you very much.Really appreciate it.

Try this

#!/usr/bin/perl

use XML::LibXSLT;
use XML::LibXML;

my $parser = XML::LibXML->new();
my $xslt = XML::LibXSLT->new();

my $source = $parser->parse_file('example.xml');
my $style_doc = $parser->parse_file('example.xsl');

my $stylesheet = $xslt->parse_stylesheet($style_doc);

my $results = $stylesheet->transform($source);

print $stylesheet->output_string($results);

For this to work you input document (example.xml) needs to be well-formed. Thus I have added a root element called "Instances".

<Instances>
   <Instance Name="New York">
      <Description></Description>
      <Instance Name="A">
         <Description></Description>
         <PropertyValue Key="false" Name="Building A" />
      </Instance>
      <Instance Name="B">
         <Description></Description>
         <PropertyValue Key="false" Name="Building B" />
      </Instance>
      <PropertyValue Key="false" Name="random" />
      <PropertyValue Key="false" Name="blabla" />
      <PropertyValue Key="false" Name="blabla2" />
   </Instance>
   <Instance Name="Mumbai">
      <Description></Description>
      <Instance Name="C">
         <Description></Description>
         <PropertyValue Key="false" Name="Building C" />
      </Instance>
      <Instance Name="D">
         <Description></Description>
         <PropertyValue Key="false" Name="Building D" />
      </Instance>
      <PropertyValue Key="false" Name="absolute" />
      <PropertyValue Key="false" Name="perl" />
      <PropertyValue Key="false" Name="xml" />
   </Instance>
</Instances>

Here is the stylesheet (example.xsl). This can handle any number of PropertyValue elements as requested.

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

   <xsl:strip-space elements="*" />

   <xsl:template match="/Instances/Instance">
       <xsl:element name='{name()}'>
           <xsl:copy-of select="Description"/>
           <xsl:for-each select="child::PropertyValue">
              <xsl:copy-of select="." />
           </xsl:for-each>
           <xsl:for-each select="child::Instance">
              <xsl:copy-of select="." />
           </xsl:for-each>
       </xsl:element><xsl:text>
</xsl:text>
   </xsl:template>

</xsl:stylesheet>

and here is the result document

<Instance>
  <Description/>
  <PropertyValue Key="false" Name="random"/>
  <PropertyValue Key="false" Name="blabla"/>
  <PropertyValue Key="false" Name="blabla2"/>
  <Instance Name="A">
    <Description/>
    <PropertyValue Key="false" Name="Building A"/>
  </Instance>
  <Instance Name="B">
    <Description/>
    <PropertyValue Key="false" Name="Building B"/>
  </Instance>
</Instance>
<Instance>
  <Description/>
  <PropertyValue Key="false" Name="absolute"/>
  <PropertyValue Key="false" Name="perl"/>
  <PropertyValue Key="false" Name="xml"/>
  <Instance Name="C">
    <Description/>
    <PropertyValue Key="false" Name="Building C"/>
  </Instance>
  <Instance Name="D">
    <Description/>
    <PropertyValue Key="false" Name="Building D"/>
  </Instance>
</Instance>

had problem with perl when executing it. I installed the necessary perl modules but it failed to run. Is there an alternative for this?

That is strange. What errors were you getting?

Sure, you can use any XSLT processor.

For example, from a GNU/Linux command line:

Perl crashed basically. I wonder if there are any other methods to do this beside using that XSLT.