joeperl has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

Im parsing a xml file which has a link to another file which inturn has a link to another file and so on.. This is achieved by using the xi:include tag.

for example...

<xi:include href="$HOME_ROOT/module/module.xml"/>

When i try to invoke the xinclude parser, it is not able to access the file even though i initialize the variable with a pre-determined path.

How to overcome this issue? I couldnt find any modules that support this scenario..

Thanks,
joe

Update

This is the sample code

use XML::DOM; use strict; use File::Find; use XML::SAX; use XML::SAX::Writer; use XML::Filter::XInclude; use File::Copy; use IO::File; my $output = new IO::File "> output.xml"; my $parser = XML::SAX::ParserFactory->parser( Handler => XML::Filter::XInclude->new( Handler => XML::SAX::Writer->new(Output=>$output) ) ); $parser->parse_uri("./project.xml");

file project.xml

<xi:include href="$HOME_ROOT/module/module1.xml"/>

file module1.xml

<xi:include href="$HOME_ROOT/module/module2.xml"/>

so the output file should ideally contain the contents of module1.xml and module2.xml.
I cant modify the ENV variable to $ENV{variable} because for that i'll ve to access the file 1st.

Replies are listed 'Best First'.
Re: Using environment variables in xi:include
by zwon (Abbot) on Jan 14, 2010 at 20:16 UTC

    It would help if you show us your code.

      This is the sample code

      use XML::DOM; use strict; use File::Find; use XML::SAX; use XML::SAX::Writer; use XML::Filter::XInclude; use File::Copy; use IO::File; my $output = new IO::File "> output.xml"; my $parser = XML::SAX::ParserFactory->parser( Handler => XML::Filter::XInclude->new( Handler => XML::SAX::Writer->new(Output=>$output) ) ); $parser->parse_uri("./project.xml");

      output.xml has a has some data and also has a xinclude, ie reference to another file in another location. As of now the paths are absolute, but can it support any variable?

        I'm not sure if I understand you correctly. Sure you can use variables instead of hardcoding the paths. You can also use Perl environment variables by using %ENV. Try the code below to get an overview.

        use strict; use warnings; foreach my $key (keys(%ENV)) { printf("%-10.10s: $ENV{$key}\n", $key); }

        Output on my system (slightly edited)

        HOME : /Users/dharry LOGNAME : dharry DISPLAY : /tmp/launch-uz3Zcp/:0 COMMAND_MO: unix2003 VERSIONER_: no PATH : /usr/bin:/bin:/usr/sbin:/sbin APP_ICON_2: ../Resources/Eclipse.icns SHELL : /bin/bash JAVA_START: 1 SSH_AUTH_S: /tmp/launch-tK7iUz/Listeners Apple_PubS: /tmp/launch-SmQdNX/Render TMPDIR : /var/folders/F9/tmp/ USER : dharry VERSIONER_: 5.10.0

        You can also set certain variables like LOGDIR.

        Cheers

        Harry

        Update

        Missed something the first time I read the post.

        When i try to invoke the xinclude parser, it is not able to access the file even though i initialize the variable with a pre-determined path.

        Does the variable contains what you think it does? Does the parser throw an error? Try adding use warnings as well. At first glance I see no reason why it shouldn't work.

Re: Using environment variables in xi:include
by ikegami (Patriarch) on Feb 19, 2010 at 07:33 UTC

    When i try to invoke the xinclude parser, it is not able to access the file even though i initialize the variable with a pre-determined path.

    You say that as if the XML parser has a concept of variables, and that it interpolates those variables into file names to include, and that it uses a perl-ish syntax for doing so. I doubt any of those are true.

    To add that feature, you'd have to modify or hook into the parser's include mechanism to add

    my %safe = map { $_ => 1 } qw( HOME_ROOT ); s/\$(\w+)/ $safe{$1} && exists($ENV{$1}) ? $ENV{$1} : "\$$1" /eg

    Update: I took a look at XML::Filter::XInclude. My suspicions were correct. But it would be easy to subclass XML::Filter::XInclude and override _include_text_document and _include_xml_document to add the functionality you want.

      Hi ikegami,
      you were right, i modified XML::FILTER::XInclude and got the ENV variables to be read as i wanted them to :)
      Thanks!