Add xmlpp.pl from http://software.decisionsoft.com/tools.html
authormike <mike>
Tue, 19 Nov 2002 12:11:48 +0000 (12:11 +0000)
committermike <mike>
Tue, 19 Nov 2002 12:11:48 +0000 (12:11 +0000)
Include a note to that effect in the README.
Work required to integrate it into the tests.

test/regression/README
test/regression/xmlpp.pl [new file with mode: 0755]

index 83d384e..fe38ee2 100644 (file)
@@ -1,4 +1,4 @@
-$Id: README,v 1.1 2002-11-03 16:53:04 mike Exp $
+$Id: README,v 1.2 2002-11-19 12:11:48 mike Exp $
 
 "queries.raw" is the file of test queries as provided by Rob.
 "mktests" parses the raw file into sections and individual queries
@@ -26,6 +26,9 @@ against its results, do this:
        ./runtests CQLParser sgmlnorm
 
 (Except that sgmlnorm is useless -- gotta find something better.)
+(That something better is xmlpp from DecisionSoft, found at
+       http://software.decisionsoft.com/tools.html
+which I will probably distribute along with cql-java.)
 
 Also: there's a nasty hack here called "showtest" which, when run like
 ``./showtest 07/03'', will show you the ways in which my output
diff --git a/test/regression/xmlpp.pl b/test/regression/xmlpp.pl
new file mode 100755 (executable)
index 0000000..a4400c4
--- /dev/null
@@ -0,0 +1,403 @@
+#!/usr/bin/perl  -w
+
+#
+#  Copyright (c) 2002, DecisionSoft Limited All rights reserved.
+#  Please see: 
+#  http://software.decisionsoft.com/license.html
+#  for more information.
+# 
+
+# $Revision: 1.1 $
+#
+# xmlpp: XML pretty printing
+#
+
+# For custom attribute sorting create an attributeOrdering.txt file that
+# lists each attributes separated by a newline in the order you would like
+# them to be sorted separated by a newline. Then use the -s option.
+
+use FileHandle;
+use Fcntl;
+use Getopt::Std;
+
+use vars qw($opt_h $opt_H $opt_s $opt_z $opt_t $opt_e $opt_S $opt_c $opt_n);
+
+my $indent=0;
+my $textContent='';
+my $lastTag=undef;
+my $output;
+my $inAnnotation = 0;
+
+
+if (!getopts('nzhHsteSc') or $opt_h) {
+    usage();
+}
+
+if ($opt_s){
+
+# expect to find attributeOrdering.txt file in same directory
+# as xmlpp is being run from
+    
+  my $scriptDir = $0;
+  if ($scriptDir =~ m#/#){
+    $scriptDir =~ s#/[^/]+$##;
+  }
+  else{
+    $scriptDir =".";
+  }
+    
+  # get attribute ordering from external file
+  if (open(SORTLIST, "<$scriptDir/attributeOrdering.txt")) {
+    @sortlist = <SORTLIST>;
+    chomp @sortlist;
+    close (SORTLIST);
+    @specialSort = grep(/^\w+/, @sortlist);
+  } 
+  else {      
+   print STDERR  "Could not open $scriptDir/attributeOrdering.txt: $!\nWARNING attribute sorting will only be alphabetic\n\n";
+  }
+}
+
+
+# set line separator to ">" speeding up parsing of XML files
+# with no line breaks 
+
+$/ = ">";
+
+
+my $sortAttributes = $opt_s;
+my $newLineComments = $opt_c;
+my $splitAttributes = $opt_t;
+my $schemaHackMode = $opt_S;
+my $normaliseWhiteSpace = $opt_n;
+
+my $filename = $ARGV[0];
+if ($opt_z && (!$filename or $filename eq '-')) {
+    print STDERR "Error: I can't edit STDIN in place.\n";
+    usage();
+}
+
+if (!$opt_z && scalar(@ARGV) > 1) {
+    print STDERR "Warning: Multiple files specified without -z option\n"; 
+}
+
+my $fh;
+
+my $stdin;
+
+if (!$filename or $filename eq '-') {
+    $fh=*STDIN;
+    $stdin=1;
+} else {
+    $fh = open_next_file() or exit(1);
+    $stdin=0;
+}
+
+do {
+    $indent=0;
+    $textContent='';
+    $lastTag=undef;
+    $output = '';
+    my $re_name = "(?:[A-Za-z0-9_:][A-Za-z0-9_:.-]*)";
+    my $re_attr = "(?:'[^']*'|\"[^\"]*\")";
+    my $input;
+
+    while ($input .= <$fh>) {
+        while ($input) {
+            if ($input =~ s/^<($re_name)((?:\s+$re_name\s*=\s*$re_attr)*\s*)(\/?)>(.*)$/$4/s ) {
+                my %attr;
+                my ($name,$attr,$selfclose) = ($1,$2,$3);
+                while ($attr =~ m/($re_name)\s*=\s*($re_attr)/gs) {
+                    my ($name,$value) = ($1,$2);
+                    $value =~ s/^["'](.*)["']$/$1/s;
+                    $attr{$name} = $value;
+                }
+                if ($opt_e) {
+                    parseStart($name, 0, %attr);
+                    if ($selfclose) { parseEnd($name) }
+                } else {
+                    parseStart($name, $selfclose, %attr);
+                }
+            } elsif ($input =~ s/^<\/($re_name)\s*>(.*)$/$2/s) {
+                parseEnd($1);
+            } elsif ($input =~ s/^<!--(.*?)-->(.*)$/$2/s) { 
+                parseComment($1);
+            } elsif ($input =~ s/^([^<]+)(.*)$/$2/s) {
+                parseDefault($1);
+            } elsif ($input =~ s/^(<\?[^>]*\?>)(.*)$/$2/s) {
+                parsePI("$1\n");
+            } elsif ($input =~ s/^(<\!DOCTYPE[^\[>]*(\[[^\]]*\])?[^>]*>)(.*)$/$3/s) {
+                parseDoctype("$1");
+            } else {
+                last;
+            }
+        }
+        if (eof($fh)) {
+            last;
+        }
+    }
+
+
+    if ($input) {
+        $input =~ m/([^\n]+)/gs;
+        print STDERR "WARNING: junk remaining on input: $1\n";
+    }
+    $fh->close();
+
+    if (!$opt_z) {
+        if(!$opt_H){ 
+            print "$output\n"
+        } else {
+            print html_escape($output)."\n"
+        }
+    } else {
+        if ($input) { 
+            print STDERR "Not overwriting file\n";
+        } else {
+            open FOUT,"> $filename" or die "Cannot overwrite file: $!";
+            if(!$opt_H){
+                print FOUT "$output\n"
+            } else {
+                print FOUT html_escape($output)."\n"
+            }
+            close FOUT
+        }
+    }
+} while (
+    !$stdin && $opt_z && ($fh = open_next_file(\$filename))
+  );
+  
+
+
+sub parseStart {
+    my $s = shift;
+    my $selfclose = shift;
+    my %attr = @_;
+
+    $textContent =~ s/\s+$//; 
+    printContent($textContent);
+
+    if($inAnnotation) {
+        return;
+    }
+
+    if($schemaHackMode and $s =~ m/(^|:)annotation$/) {
+        $inAnnotation = 1;
+        $textContent = '';
+        $lastTag = 1;
+        return;
+    }
+    if (length($output)) {
+        $output .= "\n";
+    }
+
+    $output .= "  " x $indent;
+    $output .= "<$s";
+    my @k = keys %attr;
+
+    if ($sortAttributes && (scalar(@k) > 1) ){
+
+      my @alphaSorted;
+      my @needSpecialSort;
+      my @final;
+      my $isSpecial;
+
+      # sort attributes alphabetically (default ordering)
+      @alphaSorted = sort @k;
+
+      # read through sorted list, if attribute doesn't have specified
+      # sort order, push it onto the end of the final array (this maintains
+      # alphabetic order). Else create a list that has attributes needing
+      # special ordering.
+      foreach $attribute (@alphaSorted){
+        $isSpecial = 0;
+        foreach $sortAttrib (@specialSort){
+          if ($attribute eq $sortAttrib){
+            push @needSpecialSort, $attribute;
+            $isSpecial = 1;
+          }
+        }
+        if (!$isSpecial){
+          push @final, $attribute;
+        }
+      }
+
+      # now read through the specialSort list backwards looking for
+      # any match in the needSpecialSort list. Unshift this onto the 
+      # front of the final array to maintain proper order.
+      foreach my $attribute (reverse @specialSort){
+        foreach (@needSpecialSort){
+          if ($attribute eq $_){
+            unshift @final, $attribute;
+          }
+        }
+      }
+
+      @k = @final;
+    }
+
+    foreach my $attr (@k) {
+        # 
+        # Remove (min|max)Occurs = 1 if schemaHackMode
+        #
+        if ($schemaHackMode and $attr =~ m/^(minOccurs|maxOccurs)$/ and $attr{$attr} eq "1") {
+            next;
+        }
+
+        if ($splitAttributes) {
+            $output .= "\n"."  " x $indent." ";
+        }
+        if ($attr{$attr} =~ /'/) {
+            $output .= " $attr=\"$attr{$attr}\"";
+        } else {
+            $output .= " $attr='$attr{$attr}'";
+        }
+    }
+    if ($splitAttributes and @k) {
+        $output .= "\n"."  " x $indent;
+    }
+    if ($selfclose) {
+        $output .= " />";
+        $lastTag = 0;
+    } else {
+        $output .= ">";
+        $indent++;
+        $lastTag = 1;
+    }
+    $textContent = '';
+}
+
+sub parseEnd {
+    my $s = shift;
+
+    if($inAnnotation) {
+        if($s =~ m/(^|:)annotation$/) {
+            $inAnnotation = 0;
+        }
+        return;
+    }
+
+    if($normaliseWhiteSpace) {
+        $textContent =~ s/^\s*(.*?)\s*$/$1/;
+    }
+    $indent--;
+    printContent($textContent);
+    if ($lastTag == 0) {
+        $output .= "\n";
+        $output .= "  " x $indent;
+    } 
+    $output .= "</$s>";
+    $textContent = '';
+    $lastTag = 0;
+}
+
+sub parseDefault {
+    my $s = shift;
+    if($inAnnotation) { return }
+    $textContent .= "$s";
+}
+
+sub parsePI {
+    my $s = shift;
+    $output .= "$s";
+}
+
+sub parseDoctype {
+    my $s = shift;
+    if ($s =~ /^([^\[]*\[)([^\]]*)(\].*)$/ms) {
+      $start = $1;
+      $DTD = $2;
+      $finish = $3;
+      $DTD =~ s/\</\n  \</msg;
+      $output .= "$start$DTD\n$finish\n";
+    } else {
+      $output .= "$s";
+    }
+}
+
+sub parseComment {
+    my $s = shift; 
+    if($inAnnotation) { return }
+    printContent($textContent,1);
+    if ($s =~ /([^\<]*)(<.*>)(.*)/ms) {
+      $start = $1;
+      $xml = $2;
+      $finish = $3;
+      $xml =~ s/\</\n\</msg;
+      $xml =~ s/(\n\s*\n?)+/\n/msg;
+      $xml =~ s/^\s*//msg;
+      $xml =~ s/\s*$//msg;
+      $s = "$start\n$xml\n$finish";
+    }
+    $s =~ s/\n\s*$/\n  /msg;
+    if ($newLineComments) {
+        $output .= "\n<!--$s-->\n";
+    } else {
+        $output .= "<!--$s-->";
+    }
+    $textContent='';
+}
+
+sub printContent {
+    my $s = shift;
+    my $printLF = shift;
+    my ($LF,$ret) = ("","");
+
+    if ($s =~ m/\n\s*$/) {
+        $LF = "\n"; 
+    }
+    if ($s =~ m/^[\s\n]*$/) {
+        $ret = undef;
+    } else {
+        $output .= "$s";
+        $ret = 1;
+    }
+    if ($printLF) {
+        $output .= $LF;
+    }
+}
+
+
+sub html_escape {
+    my $s = shift;
+    $s =~ s/&/&amp;/gsm;
+    $s =~ s/</&lt;/gsm;
+     $s =~ s/>/&gt;/gsm;
+    return $s;
+}
+
+sub open_next_file {
+    my $filename = shift;
+    $$filename = shift @ARGV;
+    while ($$filename and ! -f $$filename) {
+        print STDERR "WARNING: Could not find file: $$filename\n";
+        $$filename = shift @ARGV;
+    }
+    if(!$$filename) {
+        return undef;
+    }
+    my $fh = new FileHandle;
+    $fh->open("< $$filename") or die "Can't open $$filename: $!";
+    return $fh;
+}
+
+sub usage {
+    print STDERR <<EOF;
+usage: $0 [ options ] [ file.xml ... ]
+
+options:
+  -h  display this help message
+  -H  escape characters (useful for further processing)
+  -t  split attributes, one per line (useful for diff)
+  -s  sort attributes (useful for diff)
+  -z  in place edit (zap)
+  -e  expand self closing tags (useful for diff)
+  -S  schema hack mode (used by xmldiff)
+  -c  place comments on new line.
+  -n  normalise whitespace (remove leading and trailing whitespace from nodes
+      with text content.
+
+EOF
+    exit 1;
+}
+