Changeset 2631

Show
Ignore:
Timestamp:
07/30/08 13:03:01 (5 months ago)
Author:
impl
Message:

branches/david-xml_only_config_system (refs #519): Refactor libxml error reporting to throw DOMExceptions in the XML config; add AgaviXmlConfigXsltProcessor?

Location:
branches/david-xml_only_config_system/src/config
Files:
3 added
4 modified
1 moved

Legend:

Unmodified
Added
Removed
  • branches/david-xml_only_config_system/src/config/AgaviConfigCache.class.php

    r2547 r2631  
    285285    require($agaviDir . '/config/AgaviXmlConfigParser.class.php'); 
    286286    // extended DOM* classes 
    287     require($agaviDir . '/config/dom/AgaviXmlConfigDomAttr.class.php'); 
    288     require($agaviDir . '/config/dom/AgaviXmlConfigDomCharacterData.class.php'); 
    289     require($agaviDir . '/config/dom/AgaviXmlConfigDomComment.class.php'); 
    290     require($agaviDir . '/config/dom/AgaviXmlConfigDomDocument.class.php'); 
    291     require($agaviDir . '/config/dom/AgaviXmlConfigDomDocumentFragment.class.php'); 
    292     require($agaviDir . '/config/dom/AgaviXmlConfigDomDocumentType.class.php'); 
    293     require($agaviDir . '/config/dom/AgaviXmlConfigDomElement.class.php'); 
    294     require($agaviDir . '/config/dom/AgaviXmlConfigDomEntity.class.php'); 
    295     require($agaviDir . '/config/dom/AgaviXmlConfigDomEntityReference.class.php'); 
    296     require($agaviDir . '/config/dom/AgaviXmlConfigDomNode.class.php'); 
    297     require($agaviDir . '/config/dom/AgaviXmlConfigDomNotation.class.php'); 
    298     require($agaviDir . '/config/dom/AgaviXmlConfigDomProcessingInstruction.class.php'); 
    299     require($agaviDir . '/config/dom/AgaviXmlConfigDomText.class.php'); 
     287    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomAttr.class.php'); 
     288    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomCharacterData.class.php'); 
     289    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomComment.class.php'); 
     290    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomDocument.class.php'); 
     291    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomDocumentFragment.class.php'); 
     292    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomDocumentType.class.php'); 
     293    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomElement.class.php'); 
     294    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomEntity.class.php'); 
     295    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomEntityReference.class.php'); 
     296    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomNode.class.php'); 
     297    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomNotation.class.php'); 
     298    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomProcessingInstruction.class.php'); 
     299    require($agaviDir . '/config/util/dom/AgaviXmlConfigDomText.class.php'); 
     300    require($agaviDir . '/config/util/xsl/AgaviXmlConfigXsltProcessor.class.php'); 
    300301 
    301302    // manually create our config_handlers.xml handler 
  • branches/david-xml_only_config_system/src/config/AgaviXmlConfigParser.class.php

    r2626 r2631  
    7777   
    7878  /** 
    79    * @var        DOMXPath The XPath instance for the current document. 
    80    */ 
    81   protected $xpath = null; 
    82    
    83   /** 
    8479   * Test if the given document looks like an Agavi config file. 
    8580   * 
     
    132127    while($nextPath !== null) { 
    133128      $parser = new AgaviXmlConfigParser($nextPath, $environment, $context); 
     129       
    134130      $doc = $parser->execute($transformationInfo, $validationInfo); 
    135       // assign an xpath instance to each doc 
    136       $doc->xpath = new DOMXPath($doc); 
    137       // and put it on the list 
     131      // put the new document in the list 
    138132      $docs[] = $doc; 
    139133       
     
    196190        foreach($configurationElements as &$element) { 
    197191          // ... if the xpath matches, that is! 
    198           if($element->ownerDocument->xpath->evaluate($xpath, $element)) { 
     192          if($element->ownerDocument->getXpath()->evaluate($xpath, $element)) { 
    199193            // it did, so import the node and append it to the result doc 
    200194            $importedNode = $retval->importNode($element, true); 
     
    242236   * 
    243237   * @author     David Zülke <dz@bitxtender.com> 
     238   * @author     Noah Fontes <noah.fontes@bitextender.com> 
    244239   * @since      1.0.0 
    245240   */ 
     
    262257    $this->path = $path; 
    263258     
    264     $luie = libxml_use_internal_errors(true); 
    265     libxml_clear_errors(); 
    266      
    267259    // AgaviXmlConfigDomDocument has convenience methods! 
    268     $this->doc = new AgaviXmlConfigDomDocument(); 
    269     $this->doc->load($path); 
    270      
    271     if(libxml_get_last_error() !== false) { 
    272       $errors = array(); 
    273       foreach(libxml_get_errors() as $error) { 
    274         $errors[] = sprintf("Line %d: %s", $error->line, $error->message); 
    275       } 
    276       libxml_clear_errors(); 
    277       libxml_use_internal_errors($luie); 
    278       throw new AgaviParseException( 
    279         sprintf( 
    280           'Configuration file "%s" could not be parsed due to the following error%s: ' . "\n\n%s",  
    281           $path,  
    282           count($errors) > 1 ? 's' : '',  
    283           implode("\n", $errors) 
    284         ) 
    285       ); 
    286     } 
    287      
    288     // store this doc's XPath instance so we don't have to make a new one each time 
    289     $this->xpath = new DOMXPath($this->doc); 
    290      
    291     libxml_use_internal_errors($luie); 
     260    try { 
     261      $this->doc = new AgaviXmlConfigDomDocument(); 
     262      $this->doc->load($path); 
     263    } catch(DOMException $dome) { 
     264      throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: %s', $path, $dome->getMessage())); 
     265    } 
    292266  } 
    293267   
     
    300274  public function __destruct() 
    301275  { 
    302     unset($this->xpath); 
    303276    unset($this->doc); 
    304277  } 
     
    337310   * 
    338311   * @author     David Zülke <dz@bitxtender.com> 
     312   * @author     Noah Fontes <noah.fontes@bitextender.com> 
    339313   * @since      0.11.0 
    340314   */ 
    341315  public function prepare() 
    342316  { 
    343     $luie = libxml_use_internal_errors(true); 
    344     libxml_clear_errors(); 
    345      
    346317    // replace %lala% directives in XInclude href attributes 
    347318    foreach($this->doc->getElementsByTagNameNS('http://www.w3.org/2001/XInclude', '*') as $element) { 
     
    355326     
    356327    // perform xincludes 
    357     $this->doc->xinclude(); 
    358      
    359     if(libxml_get_last_error() !== false) { 
    360       $throw = false; 
    361       $errors = array(); 
    362       foreach(libxml_get_errors() as $error) { 
    363         if($error->level != LIBXML_ERR_WARNING) { 
    364           $throw = true; 
    365         } 
    366         $errors[] = sprintf("Line %d: %s", $error->line, $error->message); 
    367       } 
    368       libxml_clear_errors(); 
    369       if($throw) { 
    370         libxml_use_internal_errors($luie); 
    371         throw new AgaviParseException( 
    372           sprintf( 
    373             'Configuration file "%s" could not be parsed due to the following error%s that occured while resolving XInclude directives: ' . "\n\n%s",  
    374             $path,  
    375             count($errors) > 1 ? 's' : '',  
    376             implode("\n", $errors) 
    377           ) 
    378         ); 
    379       } 
     328    try { 
     329      $this->doc->xinclude(); 
     330    } catch(DOMException $dome) { 
     331      throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: %s', $this->path, $dome->getMessage())); 
    380332    } 
    381333     
    382334    // remove all xml:base attributes inserted by XIncludes 
    383     $nodes = $this->xpath->query('//@xml:base', $this->doc); 
     335    $nodes = $this->doc->getXpath()->query('//@xml:base', $this->doc); 
    384336    foreach($nodes as $node) { 
    385337      $node->ownerElement->removeAttributeNode($node); 
     
    393345      $this->doc->loadXML($this->doc->saveXML()); 
    394346      $this->doc->documentURI = $documentUri; 
    395        
    396       // it's a new doc, so we need a new XPath, too 
    397       $this->xpath = new DOMXPath($this->doc); 
    398     } 
    399      
    400     libxml_use_internal_errors($luie); 
     347    } 
    401348     
    402349    // next, find (and validate against) XML schema instance declarations 
     
    425372        $schema = @file_get_contents($source); 
    426373        if($schema === false) { 
    427           throw new AgaviUnreadableException( 
    428             sprintf( 
    429               'XML Schema validation file "%s" for configuration file "%s" does not exist or is unreadable', 
    430               $source, 
    431               $this->path 
    432             ) 
    433           ); 
     374          throw new AgaviUnreadableException(sprintf('XML Schema validation file "%s" for configuration file "%s" does not exist or is unreadable', $source, $this->path)); 
    434375        } 
    435376        $schemas[] = $schema; 
     
    469410   * 
    470411   * @author     David Zülke <dz@bitxtender.com> 
     412   * @author     Noah Fontes <noah.fontes@bitextender.com> 
    471413   * @since      0.11.0 
    472414   */ 
     
    475417    $transformations = array(); 
    476418     
    477     $luie = libxml_use_internal_errors(true); 
     419    $xpath = $this->doc->getXpath(); 
    478420     
    479421    // see if there are <?xml-stylesheet... processing instructions 
    480     $stylesheetProcessingInstructions = $this->xpath->query("//processing-instruction('xml-stylesheet')", $this->doc); 
     422    $stylesheetProcessingInstructions = $xpath->query("//processing-instruction('xml-stylesheet')", $this->doc); 
    481423    foreach($stylesheetProcessingInstructions as $pi) { 
    482424      // yes! alright. trick: we create a doc fragment with the contents so we don't have to parse things by hand... 
     
    490432        if(strpos($href, '#') === 0) { 
    491433          // the href points to an embedded XSL stylesheet (with ID reference), so let's see if we can find it 
    492           $stylesheets = $this->xpath->query("//*[@id='" . substr($href, 1) . "']", $this->doc); 
     434          $stylesheets = $xpath->query("//*[@id='" . substr($href, 1) . "']", $this->doc); 
    493435          if($stylesheets->length) { 
    494436            // excellent. make a new doc from that element! 
    495             $xsl = new DomDocument(); 
    496             $xsl->appendChild($xsl->importNode($stylesheets->item(0), true)); 
    497             if(libxml_get_last_error() !== false) { 
    498               $errors = array(); 
    499               foreach(libxml_get_errors() as $error) { 
    500                 $errors[] = $error->message; 
    501               } 
    502               libxml_clear_errors(); 
    503               libxml_use_internal_errors($luie); 
    504               throw new AgaviParseException( 
    505                 sprintf( 
    506                   'Configuration file "%s" could not be parsed due to the following error%s that occured while loading the specified XSL stylesheet "%s": ' . "\n\n%s",  
    507                   $this->path,  
    508                   count($errors) > 1 ? 's' : '',  
    509                   $href, 
    510                   implode("\n", $errors) 
    511                 ) 
    512               ); 
     437            try { 
     438              $xsl = new AgaviXmlConfigDomDocument(); 
     439              $xsl->appendChild($xsl->importNode($stylesheets->item(0), true)); 
     440            } catch(DOMException $dome) { 
     441              throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: Could not load XSL stylesheet "%s": %s', $this->path, $href, $dome->getMessage())); 
    513442            } 
    514443             
     
    517446            $transformations[] = $xsl; 
    518447          } else { 
    519             libxml_use_internal_errors($luie); 
    520             throw new AgaviParseException( 
    521               sprintf( 
    522                 'Configuration file "%s" could not be parsed because the inline stylesheet "%s" referenced in the "xml-stylesheet" processing instruction could not be found in the document.',  
    523                 $this->path,  
    524                 $href 
    525               ) 
    526             ); 
     448            throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed because the inline stylesheet "%s" referenced in the "xml-stylesheet" processing instruction could not be found in the document.', $this->path, $href)); 
    527449          } 
    528450        } else { 
     
    538460    // loop over all the paths we found and load the files 
    539461    foreach($transformationInfo as $href) { 
    540       $xsl = new DomDocument(); 
    541       $xsl->load($href); 
    542       if(libxml_get_last_error() !== false) { 
    543         $errors = array(); 
    544         foreach(libxml_get_errors() as $error) { 
    545           $errors[] = $error->message; 
    546         } 
    547         libxml_clear_errors(); 
    548         libxml_use_internal_errors($luie); 
    549         throw new AgaviParseException( 
    550           sprintf( 
    551             'Configuration file "%s" could not be parsed due to the following error%s that occured while loading the specified XSL stylesheet "%s": ' . "\n\n%s",  
    552             $this->path,  
    553             count($errors) > 1 ? 's' : '',  
    554             $href, 
    555             implode("\n", $errors) 
    556           ) 
    557         ); 
     462      try { 
     463        $xsl = new AgaviXmlConfigDomDocument(); 
     464        $xsl->load($href); 
     465      } catch(DOMException $dome) { 
     466        throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: Could not load XSL stylesheet "%s": %s', $this->path, $href, $dome->getMessage())); 
    558467      } 
    559468       
     
    565474    foreach($transformations as $xsl) { 
    566475      // load the stylesheet document into an XSLTProcessor instance 
    567       $proc = new XSLTProcessor(); 
    568       $proc->importStylesheet($xsl); 
    569       // libxml_get_last_error() returns false if importStylesheet failed, libxml_get_errors() works nontheless. zomfg libxml. 
    570       // also, if we catch the errors here and throw an exception, we don't need an @ further down at transformToDoc(). 
    571       if(libxml_get_last_error() !== false || count(libxml_get_errors())) { 
    572         $errors = array(); 
    573         foreach(libxml_get_errors() as $error) { 
    574           $errors[] = $error->message; 
    575         } 
    576         libxml_clear_errors(); 
    577         libxml_use_internal_errors($luie); 
    578         throw new AgaviParseException( 
    579           sprintf( 
    580             'Configuration file "%s" could not be parsed due to the following error%s that occured while importing the specified XSL stylesheet "%s": ' . "\n\n%s",  
    581             $this->path,  
    582             count($errors) > 1 ? 's' : '',  
    583             $href, 
    584             implode("\n", $errors) 
    585           ) 
    586         ); 
     476      try { 
     477        $proc = new AgaviXmlConfigXsltProcessor(); 
     478        $proc->importStylesheet($xsl); 
     479      } catch(Exception $e) { 
     480        throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: Could not import XSL stylesheet "%s": %s', $this->path, $xsl->documentURI, $e->getMessage())); 
    587481      } 
    588482       
     
    596490      )); 
    597491       
    598       // transform the doc 
    599       $newdoc = $proc->transformToDoc($this->doc); 
    600        
    601       if(libxml_get_last_error() !== false) { 
    602         $errors = array(); 
    603         foreach(libxml_get_errors() as $error) { 
    604           $errors[] = $error->message; 
    605         } 
    606         libxml_clear_errors(); 
    607         libxml_use_internal_errors($luie); 
    608         throw new AgaviParseException( 
    609           sprintf( 
    610             'Configuration file "%s" could not be parsed due to the following error%s that occured while transforming the document using the XSL stylesheet "%s": ' . "\n\n%s",  
    611             $this->path,  
    612             count($errors) > 1 ? 's' : '',  
    613             $href, 
    614             implode("\n", $errors) 
    615           ) 
    616         ); 
    617       } 
    618      
    619       if($newdoc) { 
    620         // no errors and we got a document back? excellent. this will be our new baby from now. time to kill the old one 
    621         $this->doc = $newdoc; 
    622         // and make an xpath 
    623         $this->xpath = new DOMXPath($this->doc); 
    624       } 
    625     } 
    626      
    627     libxml_use_internal_errors($luie); 
     492      try { 
     493        // transform the doc 
     494        $newdoc = $proc->transformToDoc($this->doc); 
     495      } catch(Exception $e) { 
     496        throw new AgaviParseException(sprintf('Configuration file "%s" could not be parsed: Could not transform the document using the XSL stylesheet "%s": %s', $this->path, $xsl->documentURI, $e->getMessage())); 
     497      } 
     498       
     499      // no errors and we got a document back? excellent. this will be our new baby from now. time to kill the old one 
     500       
     501      // get the old document URI 
     502      $documentUri = $this->doc->documentURI; 
     503       
     504      // and assign the new document to the old one 
     505      $this->doc = $newdoc; 
     506       
     507      // save the old document URI just in case 
     508      $this->doc->documentURI = $documentUri; 
     509    } 
    628510  } 
    629511   
     
    680562   * 
    681563   * @author     David Zülke <dz@bitxtender.com> 
     564   * @author     Noah Fontes <noah.fontes@bitextender.com> 
    682565   * @since      0.11.0 
    683566   */ 
    684567  public function validateXmlschema(array $validationFiles = array()) 
    685568  { 
    686     $luie = libxml_use_internal_errors(true); 
    687      
    688569    foreach($validationFiles as $validationFile) { 
    689570      if(!is_resource($validationFile) && !is_readable($validationFile)) { 
    690         libxml_use_internal_errors($luie); 
    691         throw new AgaviUnreadableException( 
    692           sprintf( 
    693             'XML Schema validation file "%s" for configuration file "%s" does not exist or is unreadable', 
    694             $validationFile, 
    695             $this->path 
    696           ) 
    697         ); 
     571        throw new AgaviUnreadableException(sprintf('XML Schema validation file "%s" for configuration file "%s" does not exist or is unreadable', $validationFile, $this->path)); 
    698572      } 
    699573       
    700574      // gotta do the @ to suppress warnings when the schema cannot be found 
    701       if(!@$this->doc->schemaValidate($validationFile)) { 
    702         $errors = array(); 
    703         foreach(libxml_get_errors() as $error) { 
    704           $errors[] = sprintf("Line %d: %s", $error->line, $error->message); 
    705         } 
    706         libxml_clear_errors(); 
    707         libxml_use_internal_errors($luie); 
    708         throw new AgaviParseException( 
    709           sprintf( 
    710             'XML Schema validation of configuration file "%s" failed due to the following error%s: ' . "\n\n%s",  
    711             $this->path,  
    712             count($errors) > 1 ? 's' : '',  
    713             implode("\n", $errors) 
    714           ) 
    715         ); 
    716       } 
    717     } 
    718      
    719     libxml_use_internal_errors($luie); 
     575      try { 
     576        @$this->doc->schemaValidate($validationFile); 
     577      } catch(DOMException $dome) { 
     578        throw new AgaviParseException(sprintf('XML Schema validation of configuration file "%s" failed: %s', $this->path, $dome->getMessage())); 
     579      } 
     580    } 
    720581  } 
    721582   
     
    726587   * 
    727588   * @author     David Zülke <dz@bitxtender.com> 
     589   * @author     Noah Fontes <noah.fontes@bitextender.com> 
    728590   * @since      1.0.0 
    729591   */ 
    730592  public function validateXmlschemaSource(array $validationSources = array()) 
    731593  { 
    732     $luie = libxml_use_internal_errors(true); 
    733      
    734594    foreach($validationSources as $validationSource) { 
    735       if(!@$this->doc->schemaValidateSource($validationSource)) { 
    736         $errors = array(); 
    737         foreach(libxml_get_errors() as $error) { 
    738           $errors[] = sprintf("Line %d: %s", $error->line, $error->message); 
    739         } 
    740         libxml_clear_errors(); 
    741         libxml_use_internal_errors($luie); 
    742         throw new AgaviParseException( 
    743           sprintf( 
    744             'XML Schema validation of configuration file "%s" failed due to the following error%s: ' . "\n\n%s", 
    745             $this->path, 
    746             count($errors) > 1 ? 's' : '', 
    747             implode("\n", $errors) 
    748           ) 
    749         ); 
    750       } 
    751     } 
    752      
    753     libxml_use_internal_errors($luie); 
     595      try { 
     596        @$this->doc->schemaValidateSource($validationSource); 
     597      } catch(DOMException $dome) { 
     598        throw new AgaviParseException(sprintf('XML Schema validation of configuration file "%s" failed: ' . "\n\n%s", $this->path, $dome->getMessage())); 
     599      } 
     600    } 
    754601  } 
    755602   
     
    760607   * 
    761608   * @author     David Zülke <dz@bitxtender.com> 
     609   * @author     Noah Fontes <noah.fontes@bitextender.com> 
    762610   * @since      0.11.0 
    763611   */ 
    764612  public function validateRelaxng(array $validationFiles = array()) 
    765613  { 
    766     $luie = libxml_use_internal_errors(true); 
    767      
    768614    foreach($validationFiles as $validationFile) { 
    769615      if(!is_readable($validationFile)) { 
    770         libxml_use_internal_errors($luie); 
    771         throw new AgaviUnreadableException( 
    772           sprintf( 
    773             'RELAX NG validation file "%s" for configuration file "%s" does not exist or is unreadable', 
    774             $validationFile, 
    775             $this->path 
    776           ) 
    777         ); 
     616        throw new AgaviUnreadableException(sprintf('RELAX NG validation file "%s" for configuration file "%s" does not exist or is unreadable', $validationFile, $this->path)); 
    778617      } 
    779618       
    780619      // gotta do the @ to suppress warnings when the schema cannot be found 
    781       if(!@$this->doc->relaxNGValidate($validationFile)) { 
    782         $errors = array(); 
    783         foreach(libxml_get_errors() as $error) { 
    784           $errors[] = sprintf("Line %d: %s", $error->line, $error->message); 
    785         } 
    786         libxml_clear_errors(); 
    787         libxml_use_internal_errors($luie); 
    788         throw new AgaviParseException( 
    789           sprintf( 
    790             'RELAX NG validation of configuration file "%s" failed due to the following error%s: ' . "\n\n%s",  
    791             $this->path,  
    792             count($errors) > 1 ? 's' : '',  
    793             implode("\n", $errors) 
    794           ) 
    795         ); 
    796       } 
    797     } 
    798      
    799     libxml_use_internal_errors($luie); 
     620      try { 
     621        @$this->doc->relaxNGValidate($validationFile); 
     622      } catch(DOMException $dome) { 
     623        throw new AgaviParseException(sprintf('RELAX NG validation of configuration file "%s" failed: ' . "\n\n%s", $this->path, $dome->getMessage())); 
     624      } 
     625    } 
    800626  } 
    801627   
     
    806632   * 
    807633   * @author     David Zülke <dz@bitxtender.com> 
     634   * @author     Noah Fontes <noah.fontes@bitextender.com> 
    808635   * @since      0.11.0 
    809636   */ 
     
    811638  { 
    812639    // first, we load the schematron implementation. this is an XSL document that is used to transform a .sch file to another XSL document that is then used to transform the input document. the result is informational output about the validation, which in our case must be valid ISO SVRL, an XML schema validation reporting format 
    813     $schematronIsoSvrlImplementation = new DOMDocument(); 
     640    $schematronIsoSvrlImplementation = new AgaviXmlConfigDomDocument(); 
    814641    $schematronIsoSvrlImplementation->load(AgaviConfig::get('core.agavi_dir') . '/config/schematron/iso_svrl.xsl'); 
    815     $schematron = new XSLTProcessor(); 
     642    $schematron = new AgaviXmlConfigXsltProcessor(); 
    816643    $schematron->importStylesheet($schematronIsoSvrlImplementation); 
    817644    // set some info (config file path, context name, environment name) as params 
     
    824651    )); 
    825652     
    826     $luie = libxml_use_internal_errors(true); 
    827      
    828653    // loop over all validation files. those are .sch schematron schemas, which we transform to an XSL document that is then used to validate the source document :) 
    829654    foreach($validationFiles as $href) { 
    830655      if(!is_readable($href)) { 
    831         libxml_use_internal_errors($luie); 
    832         throw new AgaviUnreadableException( 
    833           sprintf( 
    834             'Schematron validation file "%s" for configuration file "%s" does not exist or is unreadable', 
    835             $href, 
    836             $this->path 
    837           ) 
    838         ); 
     656        throw new AgaviUnreadableException(sprintf('Schematron validation file "%s" for configuration file "%s" does not exist or is unreadable', $href, $this->path)); 
    839657      } 
    840658       
    841659      // load the .sch file 
    842       $sch = new DomDocument(); 
    843       $sch->load($href); 
    844       if(libxml_get_last_error() !== false) { 
    845         $errors = array(); 
    846         foreach(libxml_get_errors() as $error) { 
    847           $errors[] = $error->message; 
    848         } 
    849         libxml_clear_errors(); 
    850         libxml_use_internal_errors($luie); 
    851         throw new AgaviParseException( 
    852           sprintf( 
    853             'Schematron validation of configuration file "%s" failed due to the following error%s that occured while loading schema file "%s": ' . "\n\n%s",  
    854             $this->path,  
    855             count($errors) > 1 ? 's' : '',  
    856             $href, 
    857             implode("\n", $errors) 
    858           ) 
    859         ); 
     660      try { 
     661        $sch = new AgaviXmlConfigDomDocument(); 
     662        $sch->load($href); 
     663      } catch(DOMException $dome) { 
     664        throw new AgaviParseException(sprintf('Schematron validation of configuration file "%s" failed: Could not load schema file "%s": %s', $this->path, $href, $dome->getMessage())); 
    860665      } 
    861666       
    862667      // is it an ISO Schematron file? 
    863668      if(!$sch->documentElement || $sch->documentElement->namespaceURI != self::SCHEMATRON_ISO_NAMESPACE) { 
    864         libxml_use_internal_errors($luie); 
    865         throw new AgaviParseException( 
    866           sprintf( 
    867             'Schematron validation of configuration file "%s" failed because schema file "%s" is invalid',  
    868             $this->path,  
    869             $href 
    870           ) 
    871         ); 
     669        throw new AgaviParseException(sprintf('Schematron validation of configuration file "%s" failed because schema file "%s" is invalid', $this->path, $href)); 
    872670      } 
    873671       
    874672      // transform the .sch file to a validation stylesheet using the schematron implementation 
    875       $schema = $schematron->transformToDoc($sch); 
    876       if($schema) { 
    877         // it transformed fine. but did we get a proper stylesheet instance at all? wrong namespaces can lead to empty docs that only have an XML prolog 
    878         if(!$schema->documentElement || $schema->documentElement->namespaceURI != self::XSL_NAMESPACE_1999) { 
    879           libxml_use_internal_errors($luie); 
    880           throw new AgaviParseException( 
    881             sprintf( 
    882               'Schematron validation of configuration file "%s" failed because schema file "%s" resulted in an invalid stylesheet',  
    883               $this->path,  
    884               $href 
    885             ) 
    886           ); 
    887         } 
    888          
    889     &nb