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