Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
288 views
in Technique[技术] by (71.8m points)

regex - update node attribute with latest datetime in XML

I have below XML:

< measCollecFile>

    < fileHeader>

            < measCollec beginTime="2013-03-14T12:10:00+00:00" />

    </ fileHeader>

    < measData>

            < measInfo>
                    < granPeriod duration="PT300S" endTime="2013-03-14T12:15:00+00:00"  />
                    < measType>VS.ave</measType>
                    < measType>VS.aveCPU</measType>

                    < measValue>VS1</measValue>
                    < measValue>VS2</measValue>
            </ measInfo>
    </ measData>
</ measCollecFile>

Q: My Problem I need to process this XML file and modify few data in certain Elements. I am able to do that with the help of this site as you can see from my previous posts.

There is a new challenge. as you can see there is datetime element in the XML as well. And I need to update this to the current datetime in the same format as it appears in the XML. i.e. the XML will always contain any date and I just to find the datetime tag and update it to the current datetime but it should be in the same format as it is in there.

Shall I take it as separate issue and treat as simple regex Perl problem and resolve accordingly as a flat file find and replace problem?

or LIBXML has anything built into to identify the datetime Tag and update it with latest datetime?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There isn't anything special to identify a "datetime" tag as you mean it. You certainly could look for attributes that fit a specific format, but is that really what you want?

Using XML::LibXML and Time::Piece to replace the beginTime with the current date:

use strict;
use warnings;

use XML::LibXML;
use Time::Piece;

my $date_format = '%Y-%m-%dT%H:%M:%S';

my $data = do { local $/; <DATA> };

my $dom = XML::LibXML->load_xml(string => $data);

for my $node ($dom->findnodes('//*[@beginTime]')) {
    if ( my $begin = $node->getAttribute('beginTime') ) {
        my ($plaindate, $tz) = split '(?=+)', $begin;
        my $date = Time::Piece->strptime($plaindate, $date_format);
        print "old beginTime = '$date'
";
        my $newdate = localtime->strftime($date_format);
        $node->setAttribute('beginTime', $newdate . $tz);
    }
}

print $dom->toString();

__DATA__
<measCollecFile>
    <fileHeader>
        <measCollec beginTime="2013-03-14T12:10:00+00:00" />
    </fileHeader>
    <measData>
        <measInfo>
            <granPeriod duration="PT300S" endTime="2013-03-14T12:15:00+00:00"  />
            <measType>VS.ave</measType>
            <measType>VS.aveCPU</measType>
            <measValue>VS1</measValue>
            <measValue>VS2</measValue>
        </measInfo>
    </measData>
</measCollecFile>

To update both beginTime and endTime, you could create a more complicated xpath:

my @attribs = qw(beginTime endTime);
my $attribs_list = join ' | ', map {'@'.$_} @attribs;

for my $node ($dom->findnodes("//*[$attribs_list]")) {
    for my $key (@attribs) {
        if ( my $att = $node->getAttribute($key) ) {
            my ($plaindate, $tz) = split '(?=+)', $att;
            my $date = Time::Piece->strptime($plaindate, $date_format);
            print "old $key = '$date'
";
            my $newdate = localtime->strftime($date_format);
            $node->setAttribute($key, $newdate . $tz);
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...