Re: LibXML: Ghost attributes

Daniel Perrett <[email protected]>
Newsgroups gmane.comp.lang.perl.xml
Message-ID <OF6AD41BD2.D5F4E9ED-ON80257577.0033372A-80257577.0033EC66@cambridge.org>
I've looked through the code again, and, as it happens, I can simply turn 
it into a simple array, 'my @sVariants', within proc_sense. This seems to 
fix the problem, so thankyou!

That said, I'm still curious as to the reason for this behaviour, as in 
theory, you might want to keep all these in memory simultaneously. Is 
keying a hash to an XML::LibXML::Element object deprecated?

Daniel





From:
Bruce Miller <[email protected]>
To:
Daniel Perrett <[email protected]>
Cc:
[email protected]
Date:
11/03/2009 18:20
Subject:
Re: LibXML: Ghost attributes



Daniel Perrett wrote:
> Hello

Hi; I haven't attempted to grok the entire code fragment,
but I'm guessing that the "Ghost" attributes are coming
from what you're putting into the hash %sVariants,
am I correct?

Since you've (apparently) declared that globally,
it accumulates whatever data you put in it throughout
the entire run (unless you empty it out by setting
it %sVariants=(); )

You're best bet would be to scope that variable
to restrict it to each file you process.
(but depending on how your code is set up,
that may end up meaning you dynamically bind
it using local rather than my, or pass it around
as an argument, or ...)

Hope that gives some hints;
bruce

> I'm using LibXML to do some processing on a directory containing some 
> highly structured dictionary data (some files have over 15k elements, 
and 
> most elements have one or more attributes), outputting to another 
folder.
> 
> I'm finding that nodes from early files start creeping into files I 
> process later (and possibly also the same file). This happens less often 

> when I create a new parser for each file, but it's not resolved.
> 
> Specifically, I am adding new attributes to newly created elements in 
one 
> file, and those attributes with those values are also appearing when I 
run 
> the same process on another file. 
> 
> The full code is very long, but below are some relevant bits, edited for 
a 
> little readability. It's also not particularly transparent what I'm 
doing 
> unless you already know the structure of the dictionary well. Basically, 

> the chunk I've isolated inserts a new element, <infs> into every <sense> 

> within an <entry>, which has attributes @id and possibly @var, the first 

> of which reads something like daily*adverb, the second is a comma 
> separated list of all the variants. Thing is, I occasionally get things 
> like <infs id="date back*verb" var="to judge by/from">...</infs> (in 
this 
> case, I've processed jk.xml (containing variant "to judge by/from") 
before 
> us_d.xml).
> 
> Is there any other housekeeping I should be doing once I get to the end 
of 
> a file or while I'm working on it? Are the references to the senses 
> colliding or something? Or is it something else more simple?
> 
> Apologies for any bad practices, I've only been using perl for 6 months 
or 
> so. Indentation is a bit out, due to copy-pasting.
> 
> Daniel
> 
> #####
> # The paths that are of interest are:
> # epp/entry/posblock/gwblock/phraserec/phrase
> #       the phrase that 'heads up' the phraserec
> # epp/entry/posblock/gwblock/phraserec/var/v 
> #       a variant form of that phrase
> # epp/entry/posblock/gwblock/phraserec/sense
> #       one 'sense' of a phrase (in this dictionary, each phrase has 
only 
> one).
> # epp/entry/posblock/gwblock/phraserec/sense/infs
> #       not in the original data, but something I create in the course 
of 
> the perl script.
> # ... where epp is the root element.
> 
> 
> my %sVariants; # each value, keyed to the sense element, is an array of 
> strings; each string is a variant of the sense element.
> 
> sub proc_file($) # called on each xml file in a directory.
> {
>         my $file=shift;
>         my $oNewParser = XML::LibXML->new;
>         $oNewParser->keep_blanks(0);
>         my $doc = $oNewParser->parse_file($file);
>         my $eRoot = $doc->documentElement();
> 
>         foreach my $eSense ($eRoot->findnodes('.//sense'))
>         {
>                 proc_sense($eSense);
>         }
> }
> 
> 
> sub proc_sense($)
> {
>         my $eSense = shift;
>         my $eEntry = get_anc($eSense, 'entry');
>         my $isPhrase;
>         my $eSW; 
> 
>         # I declare all my variables, I'm using strict, I'm sure I'll 
have 
> missed something in the lines I've copied out, but strict is happy with 
my 
> code.
>         # eSense is the <sense> element, eEntry the entry element.
>         # get_anc is a function which returns the first element going up 

> the tree that is an ancestor of the first argument with the node name in 

> the second argument
> 
>                 # Some senses are inside a phrase record element. We add 

> infs wherever this is true.
>                 if (defined ( get_anc($eSense, 'phraserec'))) 
>                 {
>                         my $ePhraserec=get_anc($eSense, 'phraserec');
>                         $eSW = 
${[$ePhraserec->findnodes('./phrase')]}[0]; 
> # there's only ever one of them
>                         if (defined ($eSW)) # just in case
>                         {
>                                 $sSW = strip_phrase($eSW); # 
strip_phrase 
> reduces a phrase to text content and removes certain child elements
>                                 $isPhrase=1;
>                         }
>                         foreach ($ePhraserec->findnodes('./*/v')) # get 
> all the variants in the phraserec
>                         {
>                                 push @{$sVariants{$eSense}}, 
> strip_phrase($_); # add the text in the variant to a list of them which 
is 
> unique to this sense
>                         }
>                 }
>                 # I also get variants from other paths in the xml, which 
I 
> haven't repeated. But these other places are all within the same xml 
file, 
> while some of the errors I get come from other xml files.
> 
>                 my $eSWinfs = $eSense->addNewChild('', 'infs');
> 
>                         my $sVarList = "";
>                         if (defined (${$sVariants{$eSense}}[0]))
>                         {
>                                 $sVarList = join (',', 
> @{$sVariants{$eSense}});
>                         }
> 
>                         if ($sSW =~ m/\w/)
>                         {
>  $eSWinfs->setAttribute('id',"$sSW\*$sPosList"); # poslist is determined 

> elsewhere within proc_sense, I've not copied out the code.
> $eSWinfs->setAttribute('var',"$sVarList") 
> if $sVarList; # offending attribute 
>                                 if ($isPhrase)
>                                 {
>  $eSWinfs->setAttribute('id',"$sSW\*phrase");
>                                 }
>                         }
> 
> }
> 
> 
> 
> _______________________________________________
> Perl-XML mailing list
> [email protected]
> To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs


-- 
[email protected]
http://math.nist.gov/~BMiller/



_______________________________________________
Perl-XML mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.