0
\$\begingroup\$

Is there a more reliable way of building a hash of the attributes associated with each SVG element?

  #-----------------------------------------------------------------------
  # Hash of SVG elements, attributes,animation from:
  # http://www.w3.org/TR/2011/REC-SVG11-20110816/attindex.html
  # Philip R Brenan at gmail dot com, 2013
  #-----------------------------------------------------------------------

  use v5.16;
  use warnings FATAL => qw(all);
  use strict;
  use Carp;
  use Data::Dump qw(dump);

  #-----------------------------------------------------------------------
  # Load elements and attributes by parsing the table supplied by W3C
  #-----------------------------------------------------------------------

  my $e; # Element, Attribute = animation
  my $a; # Attributes

  for(split(/\n/, &data))
   {s/[‘’\t,]/ /g;
    s/\A\s+//;
    s/\s+\Z//;
    my @w = split /\s+/;
    my $E = shift @w;
    $a->{$E}++; # element
    my $A = do {if ($w[-1] eq "?") {pop @w; 1} else {0}};
    for(@w)
     {$e->{$_}{$E} = $A; # Attribute to element
      $a->{$_}++; # attribute
     }
   }

  #-----------------------------------------------------------------------
  # Add presentation attributes
  #-----------------------------------------------------------------------

  for   my $E(&presentationElements)
   {for my $A(&presentationAttributes)
     {$e->{$E}{$A} = 1; # They seem to be all animatable
     }  
   }

  $$a{$_}++ for &presentationAttributes;

  #-----------------------------------------------------------------------
  # Convert to camelCase
  #-----------------------------------------------------------------------

  sub cc($) {my ($a) = @_; $a =~ s/[:_-]([a-z])/\u$1/gr}

  my $A = {map {cc($_)=>$_} keys %$a};
  my $E;
  for my $k(keys %$e)
   {for(keys %{$e->{$k}})
     {$E->{cc($k)}{cc($_)} = $e->{$k}{$_};
     }
   } 

  sub comment($)
   {my ($t) = @_;
    my $c = "#".("-"x71)."\n";
    say "\n$c# $t\n$c";
   }

  comment("SVG attribute name from perl camel case name");
  say "sub attributesFromCamelCase    {+", dump($A), "}";

  comment("Element, attribute, animation");
  say "sub elementAttributesAnimation {+", dump($E), "}";

  #-----------------------------------------------------------------------
  # http://www.w3.org/TR/2011/REC-SVG11-20110816/attindex.html#PresentationAttributes
  #-----------------------------------------------------------------------

  sub data() {<<'END'};
  ‘accent-height’   ‘font-face’ 
  ‘accumulate’  ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘additive’    ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘alphabetic’  ‘font-face’ 
  ‘amplitude’   ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’  ?
  ‘arabic-form’ ‘glyph’ 
  ‘ascent’  ‘font-face’ 
  ‘attributeName’   ‘animate’, ‘animateColor’, ‘animateTransform’, ‘set’    
  ‘attributeType’   ‘animate’, ‘animateColor’, ‘animateTransform’, ‘set’    
  ‘azimuth’ ‘feDistantLight’    ?
  ‘baseFrequency’   ‘feTurbulence’  ?
  ‘baseProfile’ ‘svg’   
  ‘bbox’    ‘font-face’ 
  ‘begin’   ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘bias’    ‘feConvolveMatrix’  ?
  ‘by’  ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘calcMode’    ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘cap-height’  ‘font-face’ 
  ‘class’   ‘a’, ‘altGlyph’, ‘circle’, ‘clipPath’, ‘defs’, ‘desc’, ‘ellipse’, ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feFlood’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMorphology’, ‘feOffset’, ‘feSpecularLighting’, ‘feTile’, ‘feTurbulence’, ‘filter’, ‘font’, ‘foreignObject’, ‘g’, ‘glyph’, ‘glyphRef’, ‘image’, ‘line’, ‘linearGradient’, ‘marker’, ‘mask’, ‘missing-glyph’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘radialGradient’, ‘rect’, ‘stop’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘title’, ‘tref’, ‘tspan’, ‘use’  ?
  ‘clipPathUnits’   ‘clipPath’  ?
  ‘contentScriptType’   ‘svg’   
  ‘contentStyleType’    ‘svg’   
  ‘cx’  ‘circle’    ?
  ‘cx’  ‘ellipse’   ?
  ‘cx’  ‘radialGradient’    ?
  ‘cy’  ‘circle’    ?
  ‘cy’  ‘ellipse’   ?
  ‘cy’  ‘radialGradient’    ?
  ‘d’   ‘path’  ?
  ‘d’   ‘glyph’, ‘missing-glyph’    
  ‘descent’ ‘font-face’ 
  ‘diffuseConstant’ ‘feDiffuseLighting’ ?
  ‘divisor’ ‘feConvolveMatrix’  ?
  ‘dur’ ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘dx’  ‘altGlyph’  ?
  ‘dx’  ‘feOffset’  ?
  ‘dx’  ‘glyphRef’  
  ‘dx’  ‘text’  ?
  ‘dx’  ‘tref’, ‘tspan’ ?
  ‘dy’  ‘altGlyph’  ?
  ‘dy’  ‘feOffset’  ?
  ‘dy’  ‘glyphRef’  
  ‘dy’  ‘text’  ?
  ‘dy’  ‘tref’, ‘tspan’ ?
  ‘edgeMode’    ‘feConvolveMatrix’  ?
  ‘elevation’   ‘feDistantLight’    ?
  ‘end’ ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘exponent’    ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’  ?
  ‘externalResourcesRequired’   ‘a’, ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘circle’, ‘clipPath’, ‘cursor’, ‘defs’, ‘ellipse’, ‘feImage’, ‘filter’, ‘font’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘linearGradient’, ‘marker’, ‘mask’, ‘mpath’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘radialGradient’, ‘rect’, ‘script’, ‘set’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’, ‘view’ 
  ‘fill’    ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘filterRes’   ‘filter’    ?
  ‘filterUnits’ ‘filter’    ?
  ‘font-family’ ‘font-face’ 
  ‘font-size’   ‘font-face’ 
  ‘font-stretch’    ‘font-face’ 
  ‘font-style’  ‘font-face’ 
  ‘font-variant’    ‘font-face’ 
  ‘font-weight’ ‘font-face’ 
  ‘format’  ‘altGlyph’  
  ‘format’  ‘glyphRef’  
  ‘from’    ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘fx’  ‘radialGradient’    ?
  ‘fy’  ‘radialGradient’    ?
  ‘g1’  ‘hkern’, ‘vkern’    
  ‘g2’  ‘hkern’, ‘vkern’    
  ‘glyph-name’  ‘glyph’ 
  ‘glyphRef’    ‘altGlyph’  
  ‘glyphRef’    ‘glyphRef’  
  ‘gradientTransform’   ‘linearGradient’    ?
  ‘gradientTransform’   ‘radialGradient’    ?
  ‘gradientUnits’   ‘linearGradient’    ?
  ‘gradientUnits’   ‘radialGradient’    ?
  ‘hanging’ ‘font-face’ 
  ‘height’  ‘filter’    ?
  ‘height’  ‘foreignObject’ ?
  ‘height’  ‘image’ ?
  ‘height’  ‘pattern’   ?
  ‘height’  ‘rect’  ?
  ‘height’  ‘svg’   ?
  ‘height’  ‘use’   ?
  ‘height’  ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feFlood’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMorphology’, ‘feOffset’, ‘feSpecularLighting’, ‘feTile’, ‘feTurbulence’   ?
  ‘height’  ‘mask’  ?
  ‘horiz-adv-x’ ‘font’  
  ‘horiz-adv-x’ ‘glyph’, ‘missing-glyph’    
  ‘horiz-origin-x’  ‘font’  
  ‘horiz-origin-y’  ‘font’  
  ‘id’  ‘a’, ‘altGlyph’, ‘altGlyphDef’, ‘altGlyphItem’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘circle’, ‘clipPath’, ‘color-profile’, ‘cursor’, ‘defs’, ‘desc’, ‘ellipse’, ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feDistantLight’, ‘feFlood’, ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMergeNode’, ‘feMorphology’, ‘feOffset’, ‘fePointLight’, ‘feSpecularLighting’, ‘feSpotLight’, ‘feTile’, ‘feTurbulence’, ‘filter’, ‘font’, ‘font-face’, ‘font-face-format’, ‘font-face-name’, ‘font-face-src’, ‘font-face-uri’, ‘foreignObject’, ‘g’, ‘glyph’, ‘glyphRef’, ‘hkern’, ‘image’, ‘line’, ‘linearGradient’, ‘marker’, ‘mask’, ‘metadata’, ‘missing-glyph’, ‘mpath’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘radialGradient’, ‘rect’, ‘script’, ‘set’, ‘stop’, ‘style’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘title’, ‘tref’, ‘tspan’, ‘use’, ‘view’, ‘vkern’  
  ‘ideographic’ ‘font-face’ 
  ‘in’  ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feGaussianBlur’, ‘feMorphology’, ‘feOffset’, ‘feSpecularLighting’, ‘feTile’    ?
  ‘in2’ ‘feBlend’   ?
  ‘in2’ ‘feComposite’   ?
  ‘in2’ ‘feDisplacementMap’ ?
  ‘intercept’   ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’  ?
  ‘k’   ‘hkern’, ‘vkern’    
  ‘k1’  ‘feComposite’   ?
  ‘k2’  ‘feComposite’   ?
  ‘k3’  ‘feComposite’   ?
  ‘k4’  ‘feComposite’   ?
  ‘kernelMatrix’    ‘feConvolveMatrix’  ?
  ‘kernelUnitLength’    ‘feConvolveMatrix’  ?
  ‘kernelUnitLength’    ‘feDiffuseLighting’ ?
  ‘kernelUnitLength’    ‘feSpecularLighting’    ?
  ‘keyPoints’   ‘animateMotion’ 
  ‘keySplines’  ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘keyTimes’    ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘lang’    ‘glyph’ 
  ‘lengthAdjust’    ‘text’, ‘textPath’, ‘tref’, ‘tspan’ ?
  ‘limitingConeAngle’   ‘feSpotLight’   ?
  ‘local’   ‘color-profile’ 
  ‘markerHeight’    ‘marker’    ?
  ‘markerUnits’ ‘marker’    ?
  ‘markerWidth’ ‘marker’    ?
  ‘maskContentUnits’    ‘mask’  ?
  ‘maskUnits’   ‘mask’  ?
  ‘mathematical’    ‘font-face’ 
  ‘max’ ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘media’   ‘style’ 
  ‘method’  ‘textPath’  ?
  ‘min’ ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘mode’    ‘feBlend’   ?
  ‘name’    ‘color-profile’ 
  ‘name’    ‘font-face-name’    
  ‘numOctaves’  ‘feTurbulence’  ?
  ‘offset’  ‘stop’  ?
  ‘offset’  ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’  ?
  ‘onabort’ ‘svg’   
  ‘onactivate’  ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onbegin’ ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘onclick’ ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onend’   ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘onerror’ ‘svg’   
  ‘onfocusin’   ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onfocusout’  ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onload’  ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onload’  ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘onmousedown’ ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onmousemove’ ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onmouseout’  ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onmouseover’ ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onmouseup’   ‘a’, ‘altGlyph’, ‘circle’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’   
  ‘onrepeat’    ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘onresize’    ‘svg’   
  ‘onscroll’    ‘svg’   
  ‘onunload’    ‘svg’   
  ‘onzoom’  ‘svg’   
  ‘operator’    ‘feComposite’   ?
  ‘operator’    ‘feMorphology’  ?
  ‘order’   ‘feConvolveMatrix’  ?
  ‘orient’  ‘marker’    ?
  ‘orientation’ ‘glyph’ 
  ‘origin’  ‘animateMotion’ 
  ‘overline-position’   ‘font-face’ 
  ‘overline-thickness’  ‘font-face’ 
  ‘panose-1’    ‘font-face’ 
  ‘path’    ‘animateMotion’ 
  ‘pathLength’  ‘path’  ?
  ‘patternContentUnits’ ‘pattern’   ?
  ‘patternTransform’    ‘pattern’   ?
  ‘patternUnits’    ‘pattern’   ?
  ‘points’  ‘polygon’   ?
  ‘points’  ‘polyline’  ?
  ‘pointsAtX’   ‘feSpotLight’   ?
  ‘pointsAtY’   ‘feSpotLight’   ?
  ‘pointsAtZ’   ‘feSpotLight’   ?
  ‘preserveAlpha’   ‘feConvolveMatrix’  ?
  ‘preserveAspectRatio’ ‘feImage’, ‘image’, ‘marker’, ‘pattern’, ‘svg’, ‘symbol’, ‘view’    ?
  ‘primitiveUnits’  ‘filter’    ?
  ‘r’   ‘circle’    ?
  ‘r’   ‘radialGradient’    ?
  ‘radius’  ‘feMorphology’  ?
  ‘refX’    ‘marker’    ?
  ‘refY’    ‘marker’    ?
  ‘rendering-intent’    ‘color-profile’ 
  ‘repeatCount’ ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘repeatDur’   ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘requiredExtensions’  ‘a’, ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘circle’, ‘clipPath’, ‘cursor’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘mask’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘rect’, ‘set’, ‘svg’, ‘switch’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’ 
  ‘requiredFeatures’    ‘a’, ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘circle’, ‘clipPath’, ‘cursor’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘mask’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘rect’, ‘set’, ‘svg’, ‘switch’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’ 
  ‘restart’ ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘result’  ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feFlood’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMorphology’, ‘feOffset’, ‘feSpecularLighting’, ‘feTile’, ‘feTurbulence’   ?
  ‘rotate’  ‘altGlyph’  ?
  ‘rotate’  ‘animateMotion’ 
  ‘rotate’  ‘text’  ?
  ‘rotate’  ‘tref’, ‘tspan’ ?
  ‘rx’  ‘ellipse’   ?
  ‘rx’  ‘rect’  ?
  ‘ry’  ‘ellipse’   ?
  ‘ry’  ‘rect’  ?
  ‘scale’   ‘feDisplacementMap’ ?
  ‘seed’    ‘feTurbulence’  ?
  ‘slope’   ‘font-face’ 
  ‘slope’   ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’  ?
  ‘spacing’ ‘textPath’  ?
  ‘specularConstant’    ‘feSpecularLighting’    ?
  ‘specularExponent’    ‘feSpecularLighting’    ?
  ‘specularExponent’    ‘feSpotLight’   ?
  ‘spreadMethod’    ‘linearGradient’    ?
  ‘spreadMethod’    ‘radialGradient’    ?
  ‘startOffset’ ‘textPath’  ?
  ‘stdDeviation’    ‘feGaussianBlur’    ?
  ‘stemh’   ‘font-face’ 
  ‘stemv’   ‘font-face’ 
  ‘stitchTiles’ ‘feTurbulence’  ?
  ‘strikethrough-position’  ‘font-face’ 
  ‘strikethrough-thickness’ ‘font-face’ 
  ‘string’  ‘font-face-format’  
  ‘style’   ‘a’, ‘altGlyph’, ‘circle’, ‘clipPath’, ‘defs’, ‘desc’, ‘ellipse’, ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feFlood’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMorphology’, ‘feOffset’, ‘feSpecularLighting’, ‘feTile’, ‘feTurbulence’, ‘filter’, ‘font’, ‘foreignObject’, ‘g’, ‘glyph’, ‘glyphRef’, ‘image’, ‘line’, ‘linearGradient’, ‘marker’, ‘mask’, ‘missing-glyph’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘radialGradient’, ‘rect’, ‘stop’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘title’, ‘tref’, ‘tspan’, ‘use’  
  ‘surfaceScale’    ‘feDiffuseLighting’ ?
  ‘surfaceScale’    ‘feSpecularLighting’    ?
  ‘systemLanguage’  ‘a’, ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘circle’, ‘clipPath’, ‘cursor’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘mask’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘rect’, ‘set’, ‘svg’, ‘switch’, ‘text’, ‘textPath’, ‘tref’, ‘tspan’, ‘use’ 
  ‘tableValues’ ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’  ?
  ‘target’  ‘a’ ?
  ‘targetX’ ‘feConvolveMatrix’  ?
  ‘targetY’ ‘feConvolveMatrix’  ?
  ‘textLength’  ‘text’  ?
  ‘textLength’  ‘textPath’, ‘tref’, ‘tspan’ ?
  ‘title’   ‘style’ 
  ‘to’  ‘set’   
  ‘to’  ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘transform’   ‘a’, ‘circle’, ‘clipPath’, ‘defs’, ‘ellipse’, ‘foreignObject’, ‘g’, ‘image’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’, ‘switch’, ‘text’, ‘use’ ?
  ‘type’    ‘animateTransform’  
  ‘type’    ‘feColorMatrix’ ?
  ‘type’    ‘feTurbulence’  ?
  ‘type’    ‘script’    
  ‘type’    ‘style’ 
  ‘type’    ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’  ?
  ‘u1’  ‘hkern’, ‘vkern’    
  ‘u2’  ‘hkern’, ‘vkern’    
  ‘underline-position’  ‘font-face’ 
  ‘underline-thickness’ ‘font-face’ 
  ‘unicode’ ‘glyph’ 
  ‘unicode-range’   ‘font-face’ 
  ‘units-per-em’    ‘font-face’ 
  ‘v-alphabetic’    ‘font-face’ 
  ‘v-hanging’   ‘font-face’ 
  ‘v-ideographic’   ‘font-face’ 
  ‘v-mathematical’  ‘font-face’ 
  ‘values’  ‘feColorMatrix’ ?
  ‘values’  ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’  
  ‘version’ ‘svg’   
  ‘vert-adv-y’  ‘font’  
  ‘vert-adv-y’  ‘glyph’, ‘missing-glyph’    
  ‘vert-origin-x’   ‘font’  
  ‘vert-origin-x’   ‘glyph’, ‘missing-glyph’    
  ‘vert-origin-y’   ‘font’  
  ‘vert-origin-y’   ‘glyph’, ‘missing-glyph’    
  ‘viewBox’ ‘marker’, ‘pattern’, ‘svg’, ‘symbol’, ‘view’    ?
  ‘viewTarget’  ‘view’  
  ‘width’   ‘filter’    ?
  ‘width’   ‘foreignObject’ ?
  ‘width’   ‘image’ ?
  ‘width’   ‘pattern’   ?
  ‘width’   ‘rect’  ?
  ‘width’   ‘svg’   ?
  ‘width’   ‘use’   ?
  ‘width’   ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feFlood’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMorphology’, ‘feOffset’, ‘feSpecularLighting’, ‘feTile’, ‘feTurbulence’   ?
  ‘width’   ‘mask’  ?
  ‘widths’  ‘font-face’ 
  ‘x’   ‘altGlyph’  ?
  ‘x’   ‘cursor’    ?
  ‘x’   ‘fePointLight’  ?
  ‘x’   ‘feSpotLight’   ?
  ‘x’   ‘filter’    ?
  ‘x’   ‘foreignObject’ ?
  ‘x’   ‘glyphRef’  
  ‘x’   ‘image’ ?
  ‘x’   ‘pattern’   ?
  ‘x’   ‘rect’  ?
  ‘x’   ‘svg’   ?
  ‘x’   ‘text’  ?
  ‘x’   ‘use’   ?
  ‘x’   ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feFlood’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMorphology’, ‘feOffset’, ‘feSpecularLighting’, ‘feTile’, ‘feTurbulence’   ?
  ‘x’   ‘mask’  ?
  ‘x’   ‘tref’, ‘tspan’ ?
  ‘x-height’    ‘font-face’ 
  ‘x1’  ‘line’  ?
  ‘x1’  ‘linearGradient’    ?
  ‘x2’  ‘line’  ?
  ‘x2’  ‘linearGradient’    ?
  ‘xChannelSelector’    ‘feDisplacementMap’ ?
  ‘xlink:actuate’   ‘a’ 
  ‘xlink:actuate’   ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘color-profile’, ‘cursor’, ‘feImage’, ‘filter’, ‘font-face-uri’, ‘glyphRef’, ‘image’, ‘mpath’, ‘pattern’, ‘script’, ‘set’, ‘use’    
  ‘xlink:arcrole’   ‘a’, ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘color-profile’, ‘cursor’, ‘feImage’, ‘filter’, ‘font-face-uri’, ‘glyphRef’, ‘image’, ‘linearGradient’, ‘mpath’, ‘pattern’, ‘radialGradient’, ‘script’, ‘set’, ‘textPath’, ‘tref’, ‘use’   
  ‘xlink:href’  ‘a’ ?
  ‘xlink:href’  ‘altGlyph’  
  ‘xlink:href’  ‘color-profile’ 
  ‘xlink:href’  ‘cursor’    ?
  ‘xlink:href’  ‘feImage’   ?
  ‘xlink:href’  ‘filter’    ?
  ‘xlink:href’  ‘font-face-uri’ 
  ‘xlink:href’  ‘glyphRef’  
  ‘xlink:href’  ‘image’ ?
  ‘xlink:href’  ‘linearGradient’    ?
  ‘xlink:href’  ‘mpath’ 
  ‘xlink:href’  ‘pattern’   ?
  ‘xlink:href’  ‘radialGradient’    ?
  ‘xlink:href’  ‘script’    
  ‘xlink:href’  ‘textPath’  ?
  ‘xlink:href’  ‘use’   ?
  ‘xlink:href’  ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘set’   
  ‘xlink:href’  ‘tref’  ?
  ‘xlink:role’  ‘a’, ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘color-profile’, ‘cursor’, ‘feImage’, ‘filter’, ‘font-face-uri’, ‘glyphRef’, ‘image’, ‘linearGradient’, ‘mpath’, ‘pattern’, ‘radialGradient’, ‘script’, ‘set’, ‘textPath’, ‘tref’, ‘use’   
  ‘xlink:show’  ‘a’ 
  ‘xlink:show’  ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘color-profile’, ‘cursor’, ‘feImage’, ‘filter’, ‘font-face-uri’, ‘glyphRef’, ‘image’, ‘mpath’, ‘pattern’, ‘script’, ‘set’, ‘use’    
  ‘xlink:title’ ‘a’, ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘color-profile’, ‘cursor’, ‘feImage’, ‘filter’, ‘font-face-uri’, ‘glyphRef’, ‘image’, ‘linearGradient’, ‘mpath’, ‘pattern’, ‘radialGradient’, ‘script’, ‘set’, ‘textPath’, ‘tref’, ‘use’   
  ‘xlink:type’  ‘a’, ‘altGlyph’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘color-profile’, ‘cursor’, ‘feImage’, ‘filter’, ‘font-face-uri’, ‘glyphRef’, ‘image’, ‘linearGradient’, ‘mpath’, ‘pattern’, ‘radialGradient’, ‘script’, ‘set’, ‘textPath’, ‘tref’, ‘use’   
  ‘xml:base’    ‘a’, ‘altGlyph’, ‘altGlyphDef’, ‘altGlyphItem’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘circle’, ‘clipPath’, ‘color-profile’, ‘cursor’, ‘defs’, ‘desc’, ‘ellipse’, ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feDistantLight’, ‘feFlood’, ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMergeNode’, ‘feMorphology’, ‘feOffset’, ‘fePointLight’, ‘feSpecularLighting’, ‘feSpotLight’, ‘feTile’, ‘feTurbulence’, ‘filter’, ‘font’, ‘font-face’, ‘font-face-format’, ‘font-face-name’, ‘font-face-src’, ‘font-face-uri’, ‘foreignObject’, ‘g’, ‘glyph’, ‘glyphRef’, ‘hkern’, ‘image’, ‘line’, ‘linearGradient’, ‘marker’, ‘mask’, ‘metadata’, ‘missing-glyph’, ‘mpath’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘radialGradient’, ‘rect’, ‘script’, ‘set’, ‘stop’, ‘style’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘title’, ‘tref’, ‘tspan’, ‘use’, ‘view’, ‘vkern’  
  ‘xml:lang’    ‘a’, ‘altGlyph’, ‘altGlyphDef’, ‘altGlyphItem’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘circle’, ‘clipPath’, ‘color-profile’, ‘cursor’, ‘defs’, ‘desc’, ‘ellipse’, ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feDistantLight’, ‘feFlood’, ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMergeNode’, ‘feMorphology’, ‘feOffset’, ‘fePointLight’, ‘feSpecularLighting’, ‘feSpotLight’, ‘feTile’, ‘feTurbulence’, ‘filter’, ‘font’, ‘font-face’, ‘font-face-format’, ‘font-face-name’, ‘font-face-src’, ‘font-face-uri’, ‘foreignObject’, ‘g’, ‘glyph’, ‘glyphRef’, ‘hkern’, ‘image’, ‘line’, ‘linearGradient’, ‘marker’, ‘mask’, ‘metadata’, ‘missing-glyph’, ‘mpath’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘radialGradient’, ‘rect’, ‘script’, ‘set’, ‘stop’, ‘style’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘title’, ‘tref’, ‘tspan’, ‘use’, ‘view’, ‘vkern’  
  ‘xml:space’   ‘a’, ‘altGlyph’, ‘altGlyphDef’, ‘altGlyphItem’, ‘animate’, ‘animateColor’, ‘animateMotion’, ‘animateTransform’, ‘circle’, ‘clipPath’, ‘color-profile’, ‘cursor’, ‘defs’, ‘desc’, ‘ellipse’, ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feDistantLight’, ‘feFlood’, ‘feFuncA’, ‘feFuncB’, ‘feFuncG’, ‘feFuncR’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMergeNode’, ‘feMorphology’, ‘feOffset’, ‘fePointLight’, ‘feSpecularLighting’, ‘feSpotLight’, ‘feTile’, ‘feTurbulence’, ‘filter’, ‘font’, ‘font-face’, ‘font-face-format’, ‘font-face-name’, ‘font-face-src’, ‘font-face-uri’, ‘foreignObject’, ‘g’, ‘glyph’, ‘glyphRef’, ‘hkern’, ‘image’, ‘line’, ‘linearGradient’, ‘marker’, ‘mask’, ‘metadata’, ‘missing-glyph’, ‘mpath’, ‘path’, ‘pattern’, ‘polygon’, ‘polyline’, ‘radialGradient’, ‘rect’, ‘script’, ‘set’, ‘stop’, ‘style’, ‘svg’, ‘switch’, ‘symbol’, ‘text’, ‘textPath’, ‘title’, ‘tref’, ‘tspan’, ‘use’, ‘view’, ‘vkern’  
  ‘y’   ‘altGlyph’  ?
  ‘y’   ‘cursor’    ?
  ‘y’   ‘fePointLight’  ?
  ‘y’   ‘feSpotLight’   ?
  ‘y’   ‘filter’    ?
  ‘y’   ‘foreignObject’ ?
  ‘y’   ‘glyphRef’  
  ‘y’   ‘image’ ?
  ‘y’   ‘pattern’   ?
  ‘y’   ‘rect’  ?
  ‘y’   ‘svg’   ?
  ‘y’   ‘text’  ?
  ‘y’   ‘use’   ?
  ‘y’   ‘feBlend’, ‘feColorMatrix’, ‘feComponentTransfer’, ‘feComposite’, ‘feConvolveMatrix’, ‘feDiffuseLighting’, ‘feDisplacementMap’, ‘feFlood’, ‘feGaussianBlur’, ‘feImage’, ‘feMerge’, ‘feMorphology’, ‘feOffset’, ‘feSpecularLighting’, ‘feTile’, ‘feTurbulence’   ?
  ‘y’   ‘mask’  ?
  ‘y’   ‘tref’, ‘tspan’ ?
  ‘y1’  ‘line’  ?
  ‘y1’  ‘linearGradient’    ?
  ‘y2’  ‘line’  ?
  ‘y2’  ‘linearGradient’    ?
  ‘yChannelSelector’    ‘feDisplacementMap’ ?
  ‘z’   ‘fePointLight’  ?
  ‘z’   ‘feSpotLight’   ?
  ‘zoomAndPan’  ‘svg’, ‘view’
  END

  #-----------------------------------------------------------------------
  # Presentation attributes
  #-----------------------------------------------------------------------

  sub presentationAttributes()
   {qw(alignment-baseline baseline-shift clip-path clip-rule clip color-interpolation-filters color-interpolation color-profile color-rendering color cursor direction display dominant-baseline enable-background fill-opacity fill-rule fill filter flood-color flood-opacity font-family font-size-adjust font-size font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width stroke text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode)
   }

  #-----------------------------------------------------------------------
  # Elements which accept presentation attributes
  #-----------------------------------------------------------------------

  sub presentationElements()
   {qw(a altGlyph animate animateColor circle clipPath defs ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feFlood feGaussianBlur feImage feMerge feMorphology feOffset feSpecularLighting feTile feTurbulence filter font foreignObject g glyph glyphRef image line linearGradient marker mask missing-glyph path pattern polygon polyline radialGradient rect stop svg switch symbol text textPath tref tspan use)
   }
\$\endgroup\$
5
\$\begingroup\$

Houston, we have a problem. I'm going to be blunt, not because I enjoy saying mean things to fellow programmers, but because there really isn't any way to sugar-coat it. This is unintentionally obfuscated Perl, the kind that gives the language a bad reputation.

Before continuing, I'd like to ask, What is the purpose of this code?

  1. If you want an SVG validator, consider using some standard XML DTD or schema validation tools. (XML validation is a solved problem; don't reinvent the wheel.)
  2. Do you want the resulting data structure to be used in, say, an SVG authoring tool? If that's the case, your question is about how to best represent a complex data structure as a Perl code literal.
  3. Are you doing this as an exercise in transforming the original W3C specification document into a more useful data structure? In that case, your question is mainly about screen scraping or text processing.

A key contributing factor to the unreadability of your code is naming. You have…

  • $a, $e
  • $A, $E ($E is used twice in the global scope. $A is used inside your first for loop as a boolean meaning "animatable", then as an iteration dummy variable for presentation attributes, then as a hashref to a data structure for all attributes.)
  • cc()
  • data()

It's not 1960, where every byte counts. Just saying camelCase() instead of cc() would help reduce mental workload. Short, cryptic variable names should only be used as iteration dummy variables in simple loops where it is absolutely obvious what it means. Your code doesn't qualify for that.


Let's assume your motivation is (3). Your for loop desperately needs a comment — not a two-line comment, but an essay. Something like…

# Process the W3C SVG 1.1 Spec, Appendix M (Attribute Index)
# http://www.w3.org/TR/2011/REC-SVG11-20110816/attindex.html
# into two data structures, $a and $e.
#
# Each line of the input contains:
#  Attribute-name (first word)
#  Elements on which the attribute may be specified (subsequent words)
#  '?' as the last word if the attribute is animatable
#
# The resulting data structure $a is a hashref whose keys are …
# and whose values are …
#
# The resulting data structure $e is a hashref whose keys are …
# and whose values are …

Instead of a here-doc string, try putting your data at the end of your code, after a __DATA__ marker, and reading from the <DATA> filehandle.


If, on the other hand, your motivation is (2), then I would suggest a different approach altogether. I would encode the data structure as

$regular_attributes = {
    non_anim('accent-height') => [qw(font-face)],
    non_anim('accumulate')    => [qw(animate animateColor animateMotion animateTransform)],
    non_anim('additive')      => [qw(animate animateColor animateMotion animateTransform)],
    non_anim('alphabetic')    => [qw(font-face)],
        anim('amplitude')     => [qw(feFuncA feFuncB feFuncG feFuncR)],
    # etc...
};

Alternatively, you could write it as a YAML data structure inside your __DATA__ section, then load it using a YAML parser. One useful feature of YAML is that it supports multiple streams, so you can have several YAML documents in your __DATA__ section. Another nice feature is that it lets you mark and reference previously mentioned chunks of data:

__DATA__
accent-height:
    anim: false
    elements:
        - font-face
accumulate:
    anim: false
    elements: &animElements
        - animate
        - animateColor
        - animateMotion
        - animateTransform
additive:
    anim: false
    elements: *animElements
# etc...
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy