How do I modify version number in XML doc - path to pass to Twig?

Discussion in 'XML' started by Sherman Willden, Aug 6, 2003.

  1. I am trying to use Perl's XML::Twig to modify a version number in an
    XML document. At the very end of this posting is an excerpt from the
    xml document. Just before the xml excerpt is the Perl code I am trying
    to use. The Xpath part of the script functions well.

    I think I need help determining the @field entry. I have tried
    //property[\@name='version']/string, version/string, and string. I get
    a "Can't modify non-lvalue subroutine call at C:\business
    copy\xml_try_scripts\try_xpath.pl line 26." Error which I think is
    caused by $field[] being null.

    Any ideas about what the @field value should be?

    Thanks;

    Sherman

    #!/usr/bin/perl -w

    use strict;
    use XML::XPath;
    use XML::XPath::XMLParser;
    use XML::Twig;

    # create an object to parse the file and field XPath queries
    # my $xpath = XML::XPath->new( filename => shift @ARGV );
    my $xpath = XML::XPath->new( filename => "Product.iap_xml" );

    # apply the path from the command line and get back a list matches
    my $field;
    my @field = "string";

    my $old_value = $xpath->find(
    "//property[\@name='version']/string/text()" );
    ## $old_value returns 2.20.0.0
    # print each node in the list
    # foreach my $node ( $old_value->get_nodelist ) {
    # print XML::XPath::XMLParser::as_string( $node ) . "\n";
    #}

    my $new_value = 2.20.0.12;
    my $t = new XML::Twig( TwigRoots =>
    { $field[string() = $old_value] => \&update },
    TwigPrintOutsideRoots => 1,);
    $t->parsefile( 'BC_HA.iap_xml' );
    $t->flush;

    sub update
    {
    my( $t, $field_elt)= @_;
    $field_elt->set_text( $new_value);
    $field_elt->print;
    }
    ## End of perl script and start of XML document

    <?xml version="1.0" encoding="UTF-8"?>
    Some comment stuff removed
    <InstallAnywhere_Deployment_Project increments="nnnn">
    <essentialScriptInfo>
    <versionID major="n" minor="n" revision="-1"/>
    <editionID> lots of numbers removed </editionID>
    <scriptID> lots of numbers removed </scriptID>
    <buildID> lots of numbers removed </buildID>
    <authorizationID>lots of numbers removed</authorizationID>
    </essentialScriptInfo>
    <installationObjects uniqueObjects="307">
    <object class="com.zerog.ia.installer.Installer" objectID="some
    numbers removed">
    <property name="classpath">
    <object class="java.util.Vector"/>
    </property>
    lots of stuff removed
    <property name="RPMSpec">
    <object class="com.zerog.ia.installer.RPMSpec" objectID="some
    numbers removed">
    <property name="enabled">
    <boolean>true</boolean>
    </property>
    <property name="name">
    <string><![CDATA[Our Product 2.2 Product Sub Name]]></string>
    </property>
    <property name="version">
    <string><![CDATA[2.20.0.0]]></string>
    </property>
    <property name="release">
    <string><![CDATA[2.20.0.0]]></string>
    </property>
    <property name="description">
    <string><![CDATA[]]></string>
    </property>
    <property name="summary">
    <string><![CDATA[<none>]]></string>
    </property>
    <property name="copyright">
    <string><![CDATA[2003]]></string>
    </property>
    <property name="url">
    <string><![CDATA[http://www.this.com]]></string>
    </property>
    <property name="distribution">
    <string><![CDATA[<none>]]></string>
    </property>
    <property name="vendor">
    <string><![CDATA[HP]]></string>
    </property>
    <property name="group">
    <string><![CDATA[Applications/System]]></string>
    </property>
    <property name="packager">
    <string><![CDATA[]]></string>
    </property>
    </object>
    </property>
    <property name="buildSettings">
    <object class="java.util.Properties">

    Lots of stuff to end of doucument removed
    Sherman Willden, Aug 6, 2003
    #1
    1. Advertising

  2. Sherman Willden wrote:

    > I am trying to use Perl's XML::Twig to modify a version number in an
    > XML document. At the very end of this posting is an excerpt from the
    > xml document. Just before the xml excerpt is the Perl code I am trying
    > to use. The Xpath part of the script functions well.


    > my $new_value = 2.20.0.12;
    > my $t = new XML::Twig( TwigRoots =>
    > { $field[string() = $old_value] => \&update },
    > TwigPrintOutsideRoots => 1,);
    > $t->parsefile( 'BC_HA.iap_xml' );
    > $t->flush;


    I think the problem comes from the fact that $field[string() = $old_value]
    is not quoted, which means that it will be executed, and string()=
    $old_value will give the error message you get.

    The XPath expression is a simple string, which needs to be quoted, the
    attribute value needs to be quoted in the expression, and finally you need
    to escap the [ after $field or Perl thinks that field is an array.

    qq{$field\[string() = "$old_value"]}

    That said, this won't work either: twig_roots needs to be able to determine
    whether an element will be processed right when the element start, not
    later when you can use the string() value.

    The best you can do is probably to use $field for the twig_roots and then
    test on the content in the handler.

    Here is a version that builds the tree for all elements, but that flushes
    them as soon as possible:


    my $field= 'string';
    my $old_value = '2.20.0.0';
    my $new_value = '2.20.0.12';

    my $t = new XML::Twig( twig_handlers =>
    { qq{$field\[string() = "$old_value"]} => \&update, # process
    __default__ => sub { $_[0]->flush; }, # flush anything else
    },
    pretty_print => 'record_c',
    );
    $t->parse( \*DATA );
    $t->flush;

    sub update
    {
    my( $t, $field_elt)= @_;
    # if you want the version number to be in a CDATA section
    # then set_content is not enough
    if( my $cdata= $field_elt->first_child_is( '#CDATA'))
    { $cdata->set_cdata( $new_value); }
    else
    { $field_elt->set_text( $new_value); }
    }


    Michel Rodriguez
    Perl &amp; XML
    http://xmltwig.com
    Michel Rodriguez, Aug 7, 2003
    #2
    1. Advertising

  3. Thank you, Michael. I will try this today.

    Sherman



    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
    sherman willden, Aug 7, 2003
    #3
  4. Thanks, Michael, for your response earlier and the code works, the
    values are modified, and the text stream is output to the screen.

    My question is how do I get a well-formed XML document from the
    results? I tried printing to a file handle ( C:\temp\twig_tmp.xml )
    but that didn't work. Below is the code that outputs the results to
    the screen.

    To further explain, I have file xyz.xml. I want to modify one value in
    the xyz.xml file and have a working xyz.xml file after the
    modification.

    I am sure that I missed the answer when reading Michael's site, Perl
    and XML, and the twig documentation. Can someone provide a reference
    to the paragraph(s) that explains what I missed?

    Thanks;

    Sherman

    #!/usr/bin/perl -w

    use strict;
    use XML::XPath;
    use XML::XPath::XMLParser;
    use XML::Twig;

    my $field= 'string';
    my $old_value = '2.20.0.0';
    my $new_value = '2.20.0.12';

    if ( -f "C:/temp/twig_tmp.xml" ) {
    chmod(0777, "C:/temp/twig_tmp.xml");
    unlink("C:/temp/twig_tmp.xml");
    }

    #open(TMPFLE, ">>c:/temp/twig_tmp.xml");

    my $t = new XML::Twig( twig_handlers =>
    { qq{$field\[string() = "$old_value"] } => \&update, # process
    __default__ => sub { $_[0]->flush; }, # flush anything
    else
    },
    pretty_print => 'record_c',);
    $t->parsefile( 'BC_HA.iap_xml' );
    #$t->print( \*TMPFLE );
    $t->flush;

    #close(TMPFLE);

    sub update
    {
    my( $t, $field_elt)= @_;
    # if you want the version number to be in a CDATA section
    # then set_content is not enough
    if( my $cdata= $field_elt->first_child_is( '#CDATA'))
    { $cdata->set_cdata( $new_value); }
    else
    { $field_elt->set_text( $new_value); }
    }
    Sherman Willden, Aug 8, 2003
    #4
  5. I have it now and my apologies to Michel Rodriguez if I gave any
    indication that it didn't work.

    I was comparing the look and file size of the output file which were
    different from the original file since I was using record_c. After
    posting this I ran a parser and the file was xml compliant. After I
    used indented_c the file size and appearance was the same as the
    original file.

    Sherman


    (Sherman Willden) wrote in message news:<>...
    > Thanks, Michael, for your response earlier and the code works, the
    > values are modified, and the text stream is output to the screen.
    >
    > My question is how do I get a well-formed XML document from the
    > results? I tried printing to a file handle ( C:\temp\twig_tmp.xml )
    > but that didn't work. Below is the code that outputs the results to
    > the screen.
    >
    > To further explain, I have file xyz.xml. I want to modify one value in
    > the xyz.xml file and have a working xyz.xml file after the
    > modification.
    >
    > I am sure that I missed the answer when reading Michael's site, Perl
    > and XML, and the twig documentation. Can someone provide a reference
    > to the paragraph(s) that explains what I missed?
    >
    > Thanks;
    >
    > Sherman
    >
    > #!/usr/bin/perl -w
    >
    > use strict;
    > use XML::XPath;
    > use XML::XPath::XMLParser;
    > use XML::Twig;
    >
    > my $field= 'string';
    > my $old_value = '2.20.0.0';
    > my $new_value = '2.20.0.12';
    >
    > if ( -f "C:/temp/twig_tmp.xml" ) {
    > chmod(0777, "C:/temp/twig_tmp.xml");
    > unlink("C:/temp/twig_tmp.xml");
    > }
    >
    > #open(TMPFLE, ">>c:/temp/twig_tmp.xml");
    >
    > my $t = new XML::Twig( twig_handlers =>
    > { qq{$field\[string() = "$old_value"] } => \&update, # process
    > __default__ => sub { $_[0]->flush; }, # flush anything
    > else
    > },
    > pretty_print => 'record_c',);
    > $t->parsefile( 'BC_HA.iap_xml' );
    > #$t->print( \*TMPFLE );
    > $t->flush;
    >
    > #close(TMPFLE);
    >
    > sub update
    > {
    > my( $t, $field_elt)= @_;
    > # if you want the version number to be in a CDATA section
    > # then set_content is not enough
    > if( my $cdata= $field_elt->first_child_is( '#CDATA'))
    > { $cdata->set_cdata( $new_value); }
    > else
    > { $field_elt->set_text( $new_value); }
    > }
    Sherman Willden, Aug 8, 2003
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matt
    Replies:
    3
    Views:
    470
    Tor Iver Wilhelmsen
    Sep 17, 2004
  2. V Green
    Replies:
    0
    Views:
    808
    V Green
    Feb 5, 2008
  3. Sherman Willden
    Replies:
    1
    Views:
    120
    Sisyphus
    Jul 25, 2003
  4. Sherman Willden
    Replies:
    3
    Views:
    161
    Sherman Willden
    Aug 8, 2003
  5. alwaysonnet

    Get XML content using XML::Twig

    alwaysonnet, Apr 21, 2010, in forum: Perl Misc
    Replies:
    19
    Views:
    180
    Klaus
    Apr 29, 2010
Loading...

Share This Page