1*cdf0e10cSrcweir: 2*cdf0e10cSrcweireval 'exec perl -wS $0 ${1+"$@"}' 3*cdf0e10cSrcweir if 0; 4*cdf0e10cSrcweir#************************************************************************* 5*cdf0e10cSrcweir# 6*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7*cdf0e10cSrcweir# 8*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates. 9*cdf0e10cSrcweir# 10*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite 11*cdf0e10cSrcweir# 12*cdf0e10cSrcweir# This file is part of OpenOffice.org. 13*cdf0e10cSrcweir# 14*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify 15*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3 16*cdf0e10cSrcweir# only, as published by the Free Software Foundation. 17*cdf0e10cSrcweir# 18*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful, 19*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of 20*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details 22*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code). 23*cdf0e10cSrcweir# 24*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License 25*cdf0e10cSrcweir# version 3 along with OpenOffice.org. If not, see 26*cdf0e10cSrcweir# <http://www.openoffice.org/license.html> 27*cdf0e10cSrcweir# for a copy of the LGPLv3 License. 28*cdf0e10cSrcweir# 29*cdf0e10cSrcweir#************************************************************************* 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir#here the definition for d would be written into dependencies. The reason is that when the event handler 32*cdf0e10cSrcweir#for the element is called, we can only find out the namespace but not the prefix. So we cannot 33*cdf0e10cSrcweir#distinguish if the namespace is used because the element was prefixed or because it uses the default 34*cdf0e10cSrcweir#namespace. 35*cdf0e10cSrcweiruse warnings; 36*cdf0e10cSrcweiruse strict; 37*cdf0e10cSrcweir 38*cdf0e10cSrcweiruse XML::Parser; 39*cdf0e10cSrcweiruse Getopt::Long; 40*cdf0e10cSrcweiruse Carp; 41*cdf0e10cSrcweir 42*cdf0e10cSrcweirsub getUpdateInfoFileName($); 43*cdf0e10cSrcweirsub writeUpdateInformationData($); 44*cdf0e10cSrcweirsub findAttribute($$); 45*cdf0e10cSrcweirsub getNotDefPrefs($$$); 46*cdf0e10cSrcweirsub collectPrefixes($$$$); 47*cdf0e10cSrcweirsub determineNsDefinitions($$$); 48*cdf0e10cSrcweirsub determineNsDefinitionForItem($$$); 49*cdf0e10cSrcweir 50*cdf0e10cSrcweirmy $inDescription = 0; 51*cdf0e10cSrcweirmy $inDependencies = 0; 52*cdf0e10cSrcweirmy $inIdentifier = 0; 53*cdf0e10cSrcweirmy $inVersion = 0; 54*cdf0e10cSrcweirmy $descNS = "http://openoffice.org/extensions/description/2006"; 55*cdf0e10cSrcweir my $indent; 56*cdf0e10cSrcweirmy $identifier; 57*cdf0e10cSrcweirmy $version; 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir#contains prefixes and the corresponding namespaces which are used in the <dependencies> 60*cdf0e10cSrcweir#element and all children of the description.xml 61*cdf0e10cSrcweirmy @usedNsInDependencies; 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir#Maps prefix to namespaces which are valid in <dependencies>. That is, they are 64*cdf0e10cSrcweir#either defined in <dependencies> or in the hirarchy above <dependencies> 65*cdf0e10cSrcweirmy %validPrefsInDep; 66*cdf0e10cSrcweir#Contains the prefixes which are defined in <dependencies> 67*cdf0e10cSrcweirmy @newPrefsInDep; 68*cdf0e10cSrcweir#Contains the prefixes/namespaces which need to be defined in <dependencies> but which are currently 69*cdf0e10cSrcweir#not. For example a prefix is defined in the parent and is used in a child of <dependencies> 70*cdf0e10cSrcweirmy %notDefInDep; 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir#prefix used in start and end element 73*cdf0e10cSrcweirmy $prefix; 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir#The default namespace valid in <dependencies> 76*cdf0e10cSrcweirmy $defNsInDep; 77*cdf0e10cSrcweir#The prefix which we use for the default namespace used in <dependencies> 78*cdf0e10cSrcweirmy $generatedPrefix; 79*cdf0e10cSrcweir 80*cdf0e10cSrcweirmy $helptext = 81*cdf0e10cSrcweir"make_ext_update_info.pl produces an update information file for an extension. ". 82*cdf0e10cSrcweir"It will use a dummy URL as URL for the extension update unless a URL has been ". 83*cdf0e10cSrcweir"provided with the --update_url option. The name of the update ". 84*cdf0e10cSrcweir"information file, which must be provided with the --out switch, should be formed ". 85*cdf0e10cSrcweir"according to this scheme: \n\n". 86*cdf0e10cSrcweir"extension_identifier.update.xml\n\n". 87*cdf0e10cSrcweir"extension_identifier should correspond to the extension identifier. In some cases ". 88*cdf0e10cSrcweir"this may not be possible because the identifier may contain characters which are not ". 89*cdf0e10cSrcweir"allowd in file names.\n\n". 90*cdf0e10cSrcweir"usage:\n". 91*cdf0e10cSrcweir"perl make_ext_update_info.pl [--help][--update_url url] --out update_information_file description.xml \n\n". 92*cdf0e10cSrcweir"Options: \n". 93*cdf0e10cSrcweir"--help - prints the help message and exits \n". 94*cdf0e10cSrcweir"--out file - the update information file to be written including the path \n". 95*cdf0e10cSrcweir"--update-url url - inserts the url under the <update-download> element. It may be necessary to enclose the urls in quotes in case they contain characters such as \"?\". ". 96*cdf0e10cSrcweir"It can be used multiple times\n\n"; 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir#handling of arguments 99*cdf0e10cSrcweirmy $help = 0; 100*cdf0e10cSrcweirmy $out; 101*cdf0e10cSrcweirmy @update_urls; 102*cdf0e10cSrcweirif (!GetOptions('help|?' => \$help, 103*cdf0e10cSrcweir 'out=s' => \$out, 104*cdf0e10cSrcweir 'update-url=s'=> \@update_urls)) 105*cdf0e10cSrcweir{ 106*cdf0e10cSrcweir print $helptext; 107*cdf0e10cSrcweir exit -1; 108*cdf0e10cSrcweir} 109*cdf0e10cSrcweirmy $cArgs = scalar @ARGV; 110*cdf0e10cSrcweirdie "You need to provide a description.xml\n\n$helptext" if $cArgs ==0; 111*cdf0e10cSrcweirdie "You need to provide the name of the update information file ". 112*cdf0e10cSrcweir "with the --out switch.\n" unless ($out); 113*cdf0e10cSrcweirdie "Too many arguments. \n\n$helptext" if $cArgs > 1; 114*cdf0e10cSrcweirprint $helptext if $help; 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir#open the update information file for writing 118*cdf0e10cSrcweirmy $FH; 119*cdf0e10cSrcweiropen $FH, "> $out" or die $!; 120*cdf0e10cSrcweir 121*cdf0e10cSrcweir#write the xml header and root element 122*cdf0e10cSrcweirprint $FH '<?xml version="1.0" encoding="UTF-8"?>', "\n"; 123*cdf0e10cSrcweirprint $FH '<description xmlns="http://openoffice.org/extensions/update/2006"', "\n"; 124*cdf0e10cSrcweirprint $FH ' xmlns:xlink="http://www.w3.org/1999/xlink">', "\n"; 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir#obtain from description.xml the data for the update information 127*cdf0e10cSrcweirwriteUpdateInformationData($ARGV[0]); 128*cdf0e10cSrcweir#We will die if there is no <version> or <identifier> in the description.xml 129*cdf0e10cSrcweirdie "Error: The description.xml does not contain a <identifier> element.\n" unless $identifier; 130*cdf0e10cSrcweirdie "Error: The description.xml does not contain a <version> element. \n" unless $version; 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir#write the write the update-download element and the children. 133*cdf0e10cSrcweir#the indention of <update-download> corresponds to that of <version> 134*cdf0e10cSrcweirprint $FH ' 'x$indent, '<update-download>', "\n"; 135*cdf0e10cSrcweir#check if update-urls have been provided through --update-url option 136*cdf0e10cSrcweirif (scalar @update_urls) 137*cdf0e10cSrcweir{ 138*cdf0e10cSrcweir my $urlIndent = $indent > 8 ? 8 : 2 * $indent; 139*cdf0e10cSrcweir #use provided urls 140*cdf0e10cSrcweir for (@update_urls) 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir print $FH ' 'x$urlIndent, '<src xlink:href="'.$_.'" />', "\n"; 143*cdf0e10cSrcweir } 144*cdf0e10cSrcweir} 145*cdf0e10cSrcweirelse 146*cdf0e10cSrcweir{ 147*cdf0e10cSrcweir #use dummy update url 148*cdf0e10cSrcweir print $FH ' 'x8, '<src xlink:href="http://extensions.openoffice.org/testarea/dummy.oxt" />', "\n"; 149*cdf0e10cSrcweir} 150*cdf0e10cSrcweirprint $FH ' 'x$indent, '</update-download>', "\n"; 151*cdf0e10cSrcweir 152*cdf0e10cSrcweirprint $FH '</description>', "\n"; 153*cdf0e10cSrcweirclose $FH; 154*cdf0e10cSrcweir 155*cdf0e10cSrcweirexit 0; 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir 158*cdf0e10cSrcweir 159*cdf0e10cSrcweirsub start_handler 160*cdf0e10cSrcweir{ 161*cdf0e10cSrcweir my $parser = shift; 162*cdf0e10cSrcweir my $name = shift; 163*cdf0e10cSrcweir 164*cdf0e10cSrcweir if ($name eq "description" 165*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) 166*cdf0e10cSrcweir { 167*cdf0e10cSrcweir $inDescription = 1; 168*cdf0e10cSrcweir } 169*cdf0e10cSrcweir elsif ($inDescription 170*cdf0e10cSrcweir && $name eq "version" 171*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) 172*cdf0e10cSrcweir { 173*cdf0e10cSrcweir $inVersion = 1; 174*cdf0e10cSrcweir $version = 1; 175*cdf0e10cSrcweir $indent = $parser->current_column(); 176*cdf0e10cSrcweir print $FH " "x$indent, $parser->original_string(); 177*cdf0e10cSrcweir } 178*cdf0e10cSrcweir elsif ($inDescription 179*cdf0e10cSrcweir && $name eq "identifier" 180*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir $inIdentifier = 1; 183*cdf0e10cSrcweir $identifier = 1; 184*cdf0e10cSrcweir print $FH " "x$parser->current_column(), $parser->original_string(); 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir elsif ($inDescription 187*cdf0e10cSrcweir && $name eq "dependencies" 188*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) 189*cdf0e10cSrcweir { 190*cdf0e10cSrcweir $inDependencies = 1; 191*cdf0e10cSrcweir my $dep = $parser->original_string(); 192*cdf0e10cSrcweir #add the additional namespace definitions, which we have discovered during the first 193*cdf0e10cSrcweir #parsing 194*cdf0e10cSrcweir #cut of the closing > or /> from the start element, so we can append the namespace definitions 195*cdf0e10cSrcweir $dep =~ /(\s*<.*) ((\s*\/>)|(\s*>))/x; 196*cdf0e10cSrcweir my $dep1 = $1; 197*cdf0e10cSrcweir $dep1.= " xmlns:".$_.'="'.$notDefInDep{$_}.'"' for (keys %notDefInDep); 198*cdf0e10cSrcweir $dep1.= $2; 199*cdf0e10cSrcweir print $FH " "x$parser->current_column(), $dep1; 200*cdf0e10cSrcweir } 201*cdf0e10cSrcweir elsif ($inDependencies) 202*cdf0e10cSrcweir { 203*cdf0e10cSrcweir #$prefix is global because we need to use it in the end element as well. 204*cdf0e10cSrcweir $prefix = ""; 205*cdf0e10cSrcweir my $fullString; 206*cdf0e10cSrcweir my $orig = $parser->original_string(); 207*cdf0e10cSrcweir #Split up the string so we can insert the prefix for the element. 208*cdf0e10cSrcweir # <OpenOffice.org-minimal-version> 209*cdf0e10cSrcweir # <d:OpenOffice.org-minimal-version> 210*cdf0e10cSrcweir $orig=~/(\s*<)(.*?)\s/x; 211*cdf0e10cSrcweir #in $2 is the element name, look for the prefix 212*cdf0e10cSrcweir if ($2 !~/(.*?):/ && $parser->namespace($name)) { 213*cdf0e10cSrcweir #no prefix, that is element uses default namespace. 214*cdf0e10cSrcweir #Now check if the default namespace in <dependencies> is the same as the one in this 215*cdf0e10cSrcweir #element. If not, then the default ns was defined "after" <dependencies>. Because all 216*cdf0e10cSrcweir #children of <dependencies> are copied into the update information, so will this default 217*cdf0e10cSrcweir #namespace definition. Hence this element will have the same default namespace in the 218*cdf0e10cSrcweir #update information. 219*cdf0e10cSrcweir my $defNsDep = $validPrefsInDep{"#default"}; 220*cdf0e10cSrcweir #we must have #default, see the if statement above 221*cdf0e10cSrcweir my $defNsCur = $parser->expand_ns_prefix("#default"); 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir if ($defNsDep eq $defNsCur) { 224*cdf0e10cSrcweir #Determine if there is in <dependency> a prefix defined (only valid there and need not 225*cdf0e10cSrcweir #directly defined in this element). If there is no prefix defined then we will 226*cdf0e10cSrcweir #add a new definition to <dependencies>. 227*cdf0e10cSrcweir for (keys %validPrefsInDep) { 228*cdf0e10cSrcweir if (($validPrefsInDep{$_} eq $defNsDep) && $_ ne "#default") { 229*cdf0e10cSrcweir $prefix = $_; last; 230*cdf0e10cSrcweir } 231*cdf0e10cSrcweir } 232*cdf0e10cSrcweir if (! $prefix) { 233*cdf0e10cSrcweir #If there was no prefix, we will add new prefix definition to <dependency> 234*cdf0e10cSrcweir #Which prefix this is has been determined during the first parsing. 235*cdf0e10cSrcweir for (keys %notDefInDep) { 236*cdf0e10cSrcweir if (($notDefInDep{$_} eq $defNsCur) && $_ ne "#default") { 237*cdf0e10cSrcweir $prefix = $_; last; 238*cdf0e10cSrcweir } 239*cdf0e10cSrcweir } 240*cdf0e10cSrcweir } 241*cdf0e10cSrcweir #die if we have no prefix 242*cdf0e10cSrcweir confess "No prefix defined for default namespace " unless $prefix; 243*cdf0e10cSrcweir #get the full part after < 244*cdf0e10cSrcweir $orig=~/(\s*<)(.*)/x; 245*cdf0e10cSrcweir $fullString= $1.$prefix.":".$2; 246*cdf0e10cSrcweir } 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir $fullString = $orig unless $fullString; 250*cdf0e10cSrcweir 251*cdf0e10cSrcweir # We record anything within <dependencies> </dependencies>. 252*cdf0e10cSrcweir print $FH $fullString; 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir} 255*cdf0e10cSrcweir 256*cdf0e10cSrcweirsub end_handler 257*cdf0e10cSrcweir{ 258*cdf0e10cSrcweir my $parser = shift; 259*cdf0e10cSrcweir my $name = shift; 260*cdf0e10cSrcweir 261*cdf0e10cSrcweir if ($name eq "description" 262*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) 263*cdf0e10cSrcweir { 264*cdf0e10cSrcweir $inDescription = 0; 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir elsif ($inDescription 267*cdf0e10cSrcweir && $name eq "version" 268*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) 269*cdf0e10cSrcweir { 270*cdf0e10cSrcweir $inVersion = 0; 271*cdf0e10cSrcweir print $FH $parser->original_string(), "\n"; 272*cdf0e10cSrcweir } 273*cdf0e10cSrcweir elsif ($inDescription 274*cdf0e10cSrcweir && $name eq "identifier" 275*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) 276*cdf0e10cSrcweir { 277*cdf0e10cSrcweir $inIdentifier = 0; 278*cdf0e10cSrcweir print $FH $parser->original_string(), "\n"; 279*cdf0e10cSrcweir } 280*cdf0e10cSrcweir elsif($inDescription 281*cdf0e10cSrcweir && $name eq "dependencies" 282*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) 283*cdf0e10cSrcweir { 284*cdf0e10cSrcweir $inDependencies = 0; 285*cdf0e10cSrcweir print $FH $parser->original_string(), "\n"; 286*cdf0e10cSrcweir } 287*cdf0e10cSrcweir elsif ($inDependencies) 288*cdf0e10cSrcweir { 289*cdf0e10cSrcweir my $orig = $parser->original_string(); 290*cdf0e10cSrcweir #$orig is empty if we have tags like this: <name /> 291*cdf0e10cSrcweir if ($orig && $prefix) { 292*cdf0e10cSrcweir $orig=~/(\s*<\/)(.*)/x; 293*cdf0e10cSrcweir $orig= $1.$prefix.":".$2; 294*cdf0e10cSrcweir } 295*cdf0e10cSrcweir print $FH $orig; 296*cdf0e10cSrcweir } 297*cdf0e10cSrcweir} 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir#We write the complete content between start and end tags of 300*cdf0e10cSrcweir# <identifier>, <version>, <dependencies> 301*cdf0e10cSrcweirsub default_handler 302*cdf0e10cSrcweir{ 303*cdf0e10cSrcweir my $parser = shift; 304*cdf0e10cSrcweir my $name = shift; 305*cdf0e10cSrcweir if ($inIdentifier || $inVersion) { 306*cdf0e10cSrcweir print $FH $parser->original_string(); 307*cdf0e10cSrcweir } elsif ($inDependencies) { 308*cdf0e10cSrcweir print $FH $parser->original_string(); 309*cdf0e10cSrcweir } 310*cdf0e10cSrcweir 311*cdf0e10cSrcweir} # End of default_handler 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir#sax handler used for the first parsing to recognize the used prefixes in <dependencies > and its 314*cdf0e10cSrcweir#children and to find out if we need to define a new prefix for the current default namespace. 315*cdf0e10cSrcweirsub start_handler_infos 316*cdf0e10cSrcweir{ 317*cdf0e10cSrcweir my $parser = shift; 318*cdf0e10cSrcweir my $name = shift; 319*cdf0e10cSrcweir if ($name eq "description" 320*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) { 321*cdf0e10cSrcweir $inDescription = 1; 322*cdf0e10cSrcweir } 323*cdf0e10cSrcweir elsif ($inDescription 324*cdf0e10cSrcweir && $name eq "dependencies" 325*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) { 326*cdf0e10cSrcweir $inDependencies = 1; 327*cdf0e10cSrcweir #build the map of prefix/namespace which are valid in <dependencies> 328*cdf0e10cSrcweir my @cur = $parser->current_ns_prefixes(); 329*cdf0e10cSrcweir for (@cur) { 330*cdf0e10cSrcweir $validPrefsInDep{$_} = $parser->expand_ns_prefix($_); 331*cdf0e10cSrcweir } 332*cdf0e10cSrcweir #remember the prefixes defined in <dependencies> 333*cdf0e10cSrcweir @newPrefsInDep = $parser->new_ns_prefixes(); 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir collectPrefixes($parser, $name, \@_, \@usedNsInDependencies); 336*cdf0e10cSrcweir return if $generatedPrefix; 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir #determine if need to create a new prefix for the current element if it uses a default ns. 339*cdf0e10cSrcweir #Split up the string so we can see if there is a prefix used 340*cdf0e10cSrcweir # <OpenOffice.org-minimal-version> 341*cdf0e10cSrcweir # <d:OpenOffice.org-minimal-version> 342*cdf0e10cSrcweir my $orig = $parser->original_string(); 343*cdf0e10cSrcweir $orig=~/(\s*<)(.*?)\s/x; 344*cdf0e10cSrcweir #in $2 is the element name, look for the prefix 345*cdf0e10cSrcweir if ($2 !~/(.*?):/ && $parser->namespace($name)) { 346*cdf0e10cSrcweir #no prefix, that is element uses default namespace. 347*cdf0e10cSrcweir #Now check if the default namespace in <dependencies> is the same as the one in this 348*cdf0e10cSrcweir #element. If not, then the default ns was defined "after" <dependencies>. Because all 349*cdf0e10cSrcweir #children of <dependencies> are copied into the update information, so will this default 350*cdf0e10cSrcweir #namespace definition. Hence this element will have the same default namespace in the 351*cdf0e10cSrcweir #update information. 352*cdf0e10cSrcweir my $defNsDep = $validPrefsInDep{"#default"}; 353*cdf0e10cSrcweir #we must have #default, see the if statement above 354*cdf0e10cSrcweir my $defNsCur = $parser->expand_ns_prefix("#default"); 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir if ($defNsDep eq $defNsCur) { 357*cdf0e10cSrcweir #Determine if there is in <dependency> a prefix defined (only valid there and need not 358*cdf0e10cSrcweir #directly defined in this element). If there is no prefix defined then we will 359*cdf0e10cSrcweir #add a new definition to <dependencies>. 360*cdf0e10cSrcweir for (keys %validPrefsInDep) { 361*cdf0e10cSrcweir if (($validPrefsInDep{$_} eq $defNsDep) && $_ ne "#default") { 362*cdf0e10cSrcweir $prefix = $_; last; 363*cdf0e10cSrcweir } 364*cdf0e10cSrcweir } 365*cdf0e10cSrcweir 366*cdf0e10cSrcweir if (! $prefix) { 367*cdf0e10cSrcweir 368*cdf0e10cSrcweir #define a new prefix 369*cdf0e10cSrcweir #actually there can be only onle prefix, which is the case when the element 370*cdf0e10cSrcweir #uses the same default namespace as <dependencies> otherwise, the default 371*cdf0e10cSrcweir #namespace was redefined by the children of <dependencies>. These are completely 372*cdf0e10cSrcweir #copied and still valid in the update information file 373*cdf0e10cSrcweir $generatedPrefix = "a"; 374*cdf0e10cSrcweir $defNsInDep = $defNsDep; 375*cdf0e10cSrcweir } 376*cdf0e10cSrcweir } 377*cdf0e10cSrcweir } 378*cdf0e10cSrcweir 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir elsif ($inDependencies) { 381*cdf0e10cSrcweir determineNsDefinitions($parser, $name, \@_); 382*cdf0e10cSrcweir collectPrefixes($parser, $name, \@_, \@usedNsInDependencies); 383*cdf0e10cSrcweir } 384*cdf0e10cSrcweir} 385*cdf0e10cSrcweir#sax handler used for the first parsing to recognize the used prefixes in <dependencies > and its 386*cdf0e10cSrcweir#children 387*cdf0e10cSrcweirsub end_handler_infos 388*cdf0e10cSrcweir{ 389*cdf0e10cSrcweir my $parser = shift; 390*cdf0e10cSrcweir my $name = shift; 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir if ($name eq "description" 393*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) { 394*cdf0e10cSrcweir $inDescription = 0; 395*cdf0e10cSrcweir } 396*cdf0e10cSrcweir elsif($inDescription 397*cdf0e10cSrcweir && $name eq "dependencies" 398*cdf0e10cSrcweir && $descNS eq $parser->namespace($name)) { 399*cdf0e10cSrcweir $inDependencies = 0; 400*cdf0e10cSrcweir } 401*cdf0e10cSrcweir} 402*cdf0e10cSrcweir 403*cdf0e10cSrcweirsub writeUpdateInformationData($) 404*cdf0e10cSrcweir{ 405*cdf0e10cSrcweir my $desc = shift; 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir #parse description xml to collect information about all used 408*cdf0e10cSrcweir #prefixes and names within <dependencies> 409*cdf0e10cSrcweir 410*cdf0e10cSrcweir my $parser = new XML::Parser(ErrorContext => 2, 411*cdf0e10cSrcweir Namespaces => 1); 412*cdf0e10cSrcweir $parser->setHandlers(Start => \&start_handler_infos, 413*cdf0e10cSrcweir End => \&end_handler_infos); 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir $parser->parsefile($desc); 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir 418*cdf0e10cSrcweir } 419*cdf0e10cSrcweir #remove duplicates in the array containing the prefixes 420*cdf0e10cSrcweir if ($generatedPrefix) { 421*cdf0e10cSrcweir my %hashtmp; 422*cdf0e10cSrcweir @usedNsInDependencies = grep(!$hashtmp{$_}++, @usedNsInDependencies); 423*cdf0e10cSrcweir 424*cdf0e10cSrcweir #check that the prefix for the default namespace in <dependencies> does not clash 425*cdf0e10cSrcweir #with any other prefixes 426*cdf0e10cSrcweir my $clash; 427*cdf0e10cSrcweir do { 428*cdf0e10cSrcweir $clash = 0; 429*cdf0e10cSrcweir for (@usedNsInDependencies) { 430*cdf0e10cSrcweir if ($_ eq $generatedPrefix) { 431*cdf0e10cSrcweir $generatedPrefix++; 432*cdf0e10cSrcweir $clash = 1; last; 433*cdf0e10cSrcweir } 434*cdf0e10cSrcweir } 435*cdf0e10cSrcweir } while ($clash); 436*cdf0e10cSrcweir $notDefInDep{$generatedPrefix} = $defNsInDep; 437*cdf0e10cSrcweir } 438*cdf0e10cSrcweir #if $notDefInDep contains the prefix #default then we need to add the generated prefix as well 439*cdf0e10cSrcweir 440*cdf0e10cSrcweir #add the special prefix for the default namespace into the map of prefixes that will be 441*cdf0e10cSrcweir #added to the <dependencies> element in the update information file 442*cdf0e10cSrcweir 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir ($inDependencies, $inDescription) = (0,0); 445*cdf0e10cSrcweir { 446*cdf0e10cSrcweir my $parser = new XML::Parser(ErrorContext => 2, 447*cdf0e10cSrcweir Namespaces => 1); 448*cdf0e10cSrcweir $parser->setHandlers( 449*cdf0e10cSrcweir Start => \&start_handler, 450*cdf0e10cSrcweir End => \&end_handler, 451*cdf0e10cSrcweir Default => \&default_handler); 452*cdf0e10cSrcweir $parser->parsefile($desc); 453*cdf0e10cSrcweir } 454*cdf0e10cSrcweir} 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir# param 1: name of the attribute we look for 457*cdf0e10cSrcweir# param 2: array of name value pairs, the first subscript is the attribute and the second 458*cdf0e10cSrcweir# is the value. 459*cdf0e10cSrcweirsub findAttribute($$) 460*cdf0e10cSrcweir{ 461*cdf0e10cSrcweir my ($name, $args_r) = @_; 462*cdf0e10cSrcweir my @args = @{$args_r}; 463*cdf0e10cSrcweir my $value; 464*cdf0e10cSrcweir while (my $attr = shift(@args)) 465*cdf0e10cSrcweir { 466*cdf0e10cSrcweir if ($attr eq $name) { 467*cdf0e10cSrcweir $value = shift(@args); 468*cdf0e10cSrcweir die "href attribut has no valid URL" unless $value; 469*cdf0e10cSrcweir last; 470*cdf0e10cSrcweir } else { # shift away the following value for the attribute 471*cdf0e10cSrcweir shift(@args); 472*cdf0e10cSrcweir } 473*cdf0e10cSrcweir } 474*cdf0e10cSrcweir return $value; 475*cdf0e10cSrcweir} 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir#collect the prefixes used in an xml element 478*cdf0e10cSrcweir#param 1: parser, 479*cdf0e10cSrcweir#param 2: element name, 480*cdf0e10cSrcweir#param 3: array of name and values of attributes 481*cdf0e10cSrcweir#param 4: out parameter, the array containing the prefixes 482*cdf0e10cSrcweirsub collectPrefixes($$$$) 483*cdf0e10cSrcweir{ 484*cdf0e10cSrcweir my $parser = shift; 485*cdf0e10cSrcweir my $name = shift; 486*cdf0e10cSrcweir my $attr_r = shift; 487*cdf0e10cSrcweir my $out_r = shift; 488*cdf0e10cSrcweir #get the prefixes which are currently valid 489*cdf0e10cSrcweir my @cur = $parser->current_ns_prefixes(); 490*cdf0e10cSrcweir my %map_ns; 491*cdf0e10cSrcweir #get the namespaces for the prefixes 492*cdf0e10cSrcweir for (@cur) { 493*cdf0e10cSrcweir if ($_ eq '#default') { 494*cdf0e10cSrcweir next; 495*cdf0e10cSrcweir } 496*cdf0e10cSrcweir my $ns = $parser->expand_ns_prefix($_); 497*cdf0e10cSrcweir $map_ns{$ns} = $_; 498*cdf0e10cSrcweir } 499*cdf0e10cSrcweir #investigat ns of element 500*cdf0e10cSrcweir my $pref = $map_ns{$parser->namespace($name)}; 501*cdf0e10cSrcweir push(@{$out_r}, $pref) if $pref; 502*cdf0e10cSrcweir #now go over the attributes 503*cdf0e10cSrcweir 504*cdf0e10cSrcweir while (my $attr = shift(@{$attr_r})) { 505*cdf0e10cSrcweir my $ns = $parser->namespace($attr); 506*cdf0e10cSrcweir if (! $ns) { 507*cdf0e10cSrcweir shift(@{$attr_r}); 508*cdf0e10cSrcweir next; 509*cdf0e10cSrcweir } 510*cdf0e10cSrcweir $pref = $map_ns{$ns}; 511*cdf0e10cSrcweir push( @{$out_r}, $pref) if $pref; 512*cdf0e10cSrcweir shift(@{$attr_r}); 513*cdf0e10cSrcweir } 514*cdf0e10cSrcweir #also add newly defined prefixes 515*cdf0e10cSrcweir my @newNs = $parser->new_ns_prefixes(); 516*cdf0e10cSrcweir for (@newNs) { 517*cdf0e10cSrcweir if ($_ eq '#default') { 518*cdf0e10cSrcweir next; 519*cdf0e10cSrcweir } 520*cdf0e10cSrcweir push (@{$out_r}, $_); 521*cdf0e10cSrcweir } 522*cdf0e10cSrcweir} 523*cdf0e10cSrcweir 524*cdf0e10cSrcweir#The function is called for each child element of dependencies. It finds out the prefixes 525*cdf0e10cSrcweir#which are used by the children and which are defined by the parents of <dependencies>. These 526*cdf0e10cSrcweir#would be lost when copying the children of <dependencies> into the update information file. 527*cdf0e10cSrcweir#Therefore these definitions are collected so that they then can be written in the <dependencies> 528*cdf0e10cSrcweir#element of the update information file. 529*cdf0e10cSrcweir#param 1: parser 530*cdf0e10cSrcweir#param 2: namsepace 531*cdf0e10cSrcweir#param 3: the @_ received in the start handler 532*cdf0e10cSrcweirsub determineNsDefinitions($$$) 533*cdf0e10cSrcweir{ 534*cdf0e10cSrcweir my ($parser, $name, $attr_r) = @_; 535*cdf0e10cSrcweir my @attr = @{$attr_r}; 536*cdf0e10cSrcweir 537*cdf0e10cSrcweir determineNsDefinitionForItem($parser, $name, 1); 538*cdf0e10cSrcweir 539*cdf0e10cSrcweir while (my $attr = shift(@attr)) { 540*cdf0e10cSrcweir determineNsDefinitionForItem($parser, $attr, 0); 541*cdf0e10cSrcweir shift @attr; 542*cdf0e10cSrcweir } 543*cdf0e10cSrcweir} 544*cdf0e10cSrcweir 545*cdf0e10cSrcweir#do not call this function for the element that does not use a prefix 546*cdf0e10cSrcweir#param 1: parser 547*cdf0e10cSrcweir#param 2: name of the element or attribute 548*cdf0e10cSrcweir#param 3: 1 if called for an elment name and 0 when called for attribue 549*cdf0e10cSrcweirsub determineNsDefinitionForItem($$$) 550*cdf0e10cSrcweir{ 551*cdf0e10cSrcweir my ($parser, $name) = @_; 552*cdf0e10cSrcweir my $ns = $parser->namespace($name); 553*cdf0e10cSrcweir if (! $ns) { 554*cdf0e10cSrcweir return; 555*cdf0e10cSrcweir } 556*cdf0e10cSrcweir #If the namespace was not kwown in <dependencies> then it was defined in one of its children 557*cdf0e10cSrcweir #or in this element. Then we are done since this namespace definition is copied into the 558*cdf0e10cSrcweir #update information. 559*cdf0e10cSrcweir my $bNsKnownInDep; 560*cdf0e10cSrcweir for ( keys %validPrefsInDep) { 561*cdf0e10cSrcweir if ( $validPrefsInDep{$_} eq $ns) { 562*cdf0e10cSrcweir $bNsKnownInDep = 1; 563*cdf0e10cSrcweir last; 564*cdf0e10cSrcweir } 565*cdf0e10cSrcweir } 566*cdf0e10cSrcweir #If the namespace of the current element is known in <dependencies> then check if the same 567*cdf0e10cSrcweir #prefix is used. If not, then the prefix was defined in one of the children of <dependencies> 568*cdf0e10cSrcweir #and was assigned the same namespace. Because we copy of children into the update information, 569*cdf0e10cSrcweir #this definition is also copied. 570*cdf0e10cSrcweir if ($bNsKnownInDep) { 571*cdf0e10cSrcweir #create a map of currently valid prefix/namespace 572*cdf0e10cSrcweir my %curPrefToNs; 573*cdf0e10cSrcweir my @curNs = $parser->current_ns_prefixes(); 574*cdf0e10cSrcweir for (@curNs) { 575*cdf0e10cSrcweir $curPrefToNs{$_} = $parser->expand_ns_prefix($_); 576*cdf0e10cSrcweir } 577*cdf0e10cSrcweir #find the prefix used in <dependencies> to define the namespace of the current element 578*cdf0e10cSrcweir my $validDepPref; 579*cdf0e10cSrcweir for (keys %validPrefsInDep) { 580*cdf0e10cSrcweir if ($validPrefsInDep{$_} eq $ns) { 581*cdf0e10cSrcweir #ignore #default 582*cdf0e10cSrcweir next if $_ eq "#default"; 583*cdf0e10cSrcweir $validDepPref = $_; 584*cdf0e10cSrcweir last; 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir } 587*cdf0e10cSrcweir #find the prefix defined in the current element used for the namespace of the element 588*cdf0e10cSrcweir my $curPref; 589*cdf0e10cSrcweir for (keys %curPrefToNs) { 590*cdf0e10cSrcweir if ($curPrefToNs{$_} eq $ns) { 591*cdf0e10cSrcweir #ignore #default 592*cdf0e10cSrcweir next if $_ eq "#default"; 593*cdf0e10cSrcweir $curPref = $_; 594*cdf0e10cSrcweir last; 595*cdf0e10cSrcweir } 596*cdf0e10cSrcweir } 597*cdf0e10cSrcweir if ($curPref && $validDepPref && ($curPref eq $validDepPref)) { 598*cdf0e10cSrcweir #If the prefixes and ns are the same, then the prefix definition of <dependencies> or its 599*cdf0e10cSrcweir #parent can be used. However, we need to find out which prefixed are NOT defined in 600*cdf0e10cSrcweir #<dependencies> so we can add them to it when we write the update information. 601*cdf0e10cSrcweir my $bDefined = 0; 602*cdf0e10cSrcweir for (@newPrefsInDep) { 603*cdf0e10cSrcweir if ($curPref eq $_) { 604*cdf0e10cSrcweir $bDefined = 1; 605*cdf0e10cSrcweir last; 606*cdf0e10cSrcweir } 607*cdf0e10cSrcweir } 608*cdf0e10cSrcweir if (! $bDefined) { 609*cdf0e10cSrcweir $notDefInDep{$curPref} = $ns; 610*cdf0e10cSrcweir } 611*cdf0e10cSrcweir } 612*cdf0e10cSrcweir } 613*cdf0e10cSrcweir} 614