0

I am trying to create a script in Unix to Parse a nested XML. Sample below:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<deployments>
    <appName>apptest</appName>
    <envVariable>app</envVariable>
    <fileSourceFolder>/sourceTest</fileSourceFolder>
    <fileBackupFolder>/testbackup</fileBackupFolder>
    <requireRestart>false</requireRestart>
    <restartCommandPath>bin</restartCommandPath>
    <deployment-files>
        <deployment-file>
            <deploymentFolder>deployment-folder</deploymentFolder>
            <fileName>test-file</fileName>
        </deployment-file>
    </deployment-files>
    <restart-commands>
        <restart-command>
            <commandName>./appstop</commandName>
        </restart-command>
        <restart-command>
            <commandName>./appstart</commandName>
        </restart-command>
    </restart-commands>
</deployments>

I need to iterate through deployment-files and restart-command elements. I read about using Perl and the installed version is 5.8.8. However I cannot use TWIG and other XML stuff in perl because of lack of libraries. I read about other stuffs too like xml_grep, xmllint , etc but those are not installed in the machine I use and I cannot manually install those or even request for it because of a lot of constraints.

I already tried using XML::Simple based on example at http://interoperating.info/courses/perl4data/node/26 but still no good.

Please advise on how to create the simplest perl or shell script for this and please provide references. I am still new in shell script and I just started to explore perl yesterday so I will appreciate all your help. Thank you.

NothingBox
  • 345
  • 5
  • 15
  • Have you tried anything from yourself? – serenesat Dec 22 '15 at 08:47
  • Yes, I did try many things from the internet. I tried to modify those to suit my needs but still not works for my requirement. I am basically new to shell script and I just tried perl yesterday so I really need help. Thanks a lot for your patience in advance – NothingBox Dec 22 '15 at 08:50
  • Can you post atleast one thing that show your effort? – serenesat Dec 22 '15 at 09:06
  • The best thing to do is to install an XML tool. If you don't have permissions to install one system-wide, you can do so in your home directory. See [this question](http://stackoverflow.com/q/540640/2088135) (and questions linked within) for details on installing perl modules locally. – Tom Fenech Dec 22 '15 at 09:07
  • @serenesat, I tried sing XML::Simple but one thing I noticed, it does not work if check **deployment-file** with only one entry. It cannot recognize one entry as array (_Not an ARRAY reference at ./perll.pl line 12._. Please take note that I modified the XMl file when i tried this. Code below: #use strict; use XML::Simple; my $deployments = XMLin('deployment-setting.xml'); foreach my $deployment (@{$deployments ->{deployment}}) { print $deployment->{deploymentFolder} . "\n"; } – NothingBox Dec 22 '15 at 09:14
  • @TomFenech, thanks a lot. I'll check your link. – NothingBox Dec 22 '15 at 09:15
  • It would be helpful if you showed us your desired output or described what it was you wanted to do with the contents of the elements that you're interested in. – Tom Fenech Dec 22 '15 at 09:19
  • Hi @TomFenech, I'm planning to create an auto deployment script using shell script or perl. Last choice is to use java which I am more familiar with. The xml file will contain information for deployment. Example, under **deployment-files**, it will loop through the elements and for each entry, there will be script to backup, copy and replace the files. Each loop of **restart-commands** will call batch/sh scripts defined in its elements. Hope I explained it well. Thank you in advance. – NothingBox Dec 22 '15 at 09:28
  • You should edit your question to add this detail, along with your attempt. It sounds like a perl script would be a good choice. – Tom Fenech Dec 22 '15 at 09:29
  • 1
    Do not use XML::Simple. Read this [Why is XML::Simple “Discouraged”?](http://stackoverflow.com/q/33267765/4248931) and add your code in your question by using edit button. Do not write code in comment. – serenesat Dec 22 '15 at 09:30
  • Escalate to whoever is asking you to do this work. 5.8.8 is end of life - and has been for several years. CPAN libraries are by FAR the best way to create maintainable and robust code on your server. Otherwise they're actually asking you to (re)write and XML parser, which is at best a complete waste of effort, and that's assuming you get exactly right and bug free. – Sobrique Dec 22 '15 at 09:38
  • @Sobrique, it is only a case study for the change suggestion in our dpeloyment plans. Since the process involves difference teams, it would be hard to request for any updates for the server. We initially planned to use scripts for maintainabilty but it seems it would be more difficult. Anyways, if there is no other solution, I will just use java for this requirement. Thank you guys for your input. – NothingBox Dec 22 '15 at 09:48
  • There is a solution - it's trivially easy. It's just much harder if you insist on hand rolling an XML parser and using a 7 year old version of perl. – Sobrique Dec 22 '15 at 10:01

1 Answers1

1

Look, I know you said 'I can't install stuff' - but the problem you've got is you're trying to parse XML without a parser, and you're using a 7 year old version of perl that is end of life. Perl 5.8.8 is end of life, and released in 2008.

That isn't a route to a good solution however hard you try - use a parser and this becomes trivially simple:

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;

my $twig = XML::Twig -> new -> parse ( \*DATA );
foreach my $deployment_files ( $twig -> get_xpath ( '//deployment-file' ) ) {
   print $deployment_files -> first_child_text('deploymentFolder'), " => ";
   print $deployment_files -> first_child_text('fileName');
   print "\n";
}

foreach my $restart_command ( $twig -> get_xpath ( '//restart-command/commandName' ) ) {
   print $restart_command -> text,"\n";
}

__DATA__
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<deployments>
    <appName>apptest</appName>
    <envVariable>app</envVariable>
    <fileSourceFolder>/sourceTest</fileSourceFolder>
    <fileBackupFolder>/testbackup</fileBackupFolder>
    <requireRestart>false</requireRestart>
    <restartCommandPath>bin</restartCommandPath>
    <deployment-files>
        <deployment-file>
            <deploymentFolder>deployment-folder</deploymentFolder>
            <fileName>test-file</fileName>
        </deployment-file>
    </deployment-files>
    <restart-commands>
        <restart-command>
            <commandName>./appstop</commandName>
        </restart-command>
        <restart-command>
            <commandName>./appstart</commandName>
        </restart-command>
    </restart-commands>
</deployments>

Without a parser, you first... have to write a parser. You can do this - the spec is well defined. But practically speaking, there is no point when there are several good XML parsers readily available that are tested and working. But even if you did, you're running in on a 7 year old interpreter. It's really not hard to do a source build of perl, and install in an alternate location.

So I would suggest the right answer here involves requesting the necessary elements to do a decent job. You wouldn't expect a carpenter to come around your hammer smashing screws in with a hammer, because he can't be bothered to procure a screwdriver, now would you?

Sobrique
  • 52,974
  • 7
  • 60
  • 101
  • I tried using Twig but I always encounter Can't locate XML/Twig.pm in @INC error. The initial plan is to provide whatever script we make to deployment team to automate copying/backup of files and restart of application. If ever additional libraries is needed to do this (Xml parser libraries for example), this will go through series of request first and lot of explanation. The mgmt is very strict on any modification in the prod servers. Anyways, I will still try to do whatever is possible in my test machine and hope it will be allowed to be implemented on prod. Thanks a lot for help. – NothingBox Dec 22 '15 at 10:27
  • Change control is about controlling change. That's fine. You have a change and a reason to make it. This is about making repeatable supportable code - that's a _good_ reason to make a change. – Sobrique Dec 22 '15 at 10:28