Exponential 6.0.13 Exponential Enterprise Open Source CMS - PHP Class Reference

ezxmlinputparser.php
Go to the documentation of this file.
1 <?php
11 /*
12 Base class for the input parser.
13 The goal of the parser is XML/HTML analyzing, fixing and transforming.
14 The input is processed in 2 passes:
15 - 1st pass: Parsing input, check for syntax errors, build DOM tree.
16 - 2nd pass: Walking through DOM tree, checking validity by XML schema,
17 calling tag handlers to transform the tree.
18
19 Both passes are controlled by the arrays described bellow and user handler functions.
20
21 */
22
23 // if ( !class_exists( 'eZXMLSchema' ) ) // AS 21-09-2007: commented out because of include_once being commented out
24 class eZXMLInputParser
25 {
27 const SHOW_NO_ERRORS = 0;
28 const SHOW_SCHEMA_ERRORS = 1;
29 const SHOW_ALL_ERRORS = 2;
30
32 const ERROR_NONE = 0;
33 const ERROR_SYNTAX = 4;
34 const ERROR_SCHEMA = 8;
35 const ERROR_DATA = 16;
36 const ERROR_ALL = 28; // 4+8+16
37
38 /* $InputTags array contains properties of elements that come from the input.
39
40 Each array element describes a tag that comes from the input. Arrays index is
41 a tag's name. Each element is an array that may contain the following members:
42
43 'name' - a string representing a new name of the tag,
44 'nameHandler' - a name of the function that returns new tag name. Function format:
45 function tagNameHandler( $tagName, &$attributes )
46
47 If no of those elements are defined the original tag's name is used.
48
49 'noChildren' - boolean value that determines if this tag could have child tags,
50 default value is false.
51
52 Example:
53
54 public $InputTags = array(
55
56 'original-name' => array( 'name' => 'new-name' ),
57
58 'original-name2' => array( 'nameHandler' => 'tagNameHandler',
59 'noChildren' => true ),
60
61 ...
62
63 );
64 */
65
66 public $InputTags = array();
67
68 /*
69 $OutputTags array contains properties of elements that are produced in the output.
70 Each array element describes a tag presented in the output. Arrays index is
71 a tag's name. Each element is an array that may contain the following members:
72
73 'parsingHandler' - "Parsing handler" called at parse pass 1 before processing tag's children.
74 'initHandler' - "Init handler" called at pass 2 before proccessing tag's children.
75 'structHandler' - "Structure handler" called at pass 2 after proccessing tag's children,
76 but before schema validity check. It can be used to implement structure
77 transformations.
78 'publishHandler' - "Publish handler" called at pass 2 after schema validity check, so it is called
79 in case the element has it's guaranteed place in the DOM tree.
80
81 'attributes' - an array that describes attributes transformations. Array's index is the
82 original name of an attribute, and the value is the new name.
83
84 'requiredInputAttributes' - attributes that are required in the input tag. If they are not presented
85 it raises invalid input flag.
86
87 Example:
88
89 public $OutputTags = array(
90
91 'custom' => array( 'parsingHandler' => 'parsingHandlerCustom',
92 'initHandler' => 'initHandlerCustom',
93 'structHandler' => 'structHandlerCustom',
94 'publishHandler' => 'publishHandlerCustom',
95 'attributes' => array( 'title' => 'name' ) ),
96
97 ...
98 );
99
100 */
101
102 public $OutputTags = array();
103
104 public $Namespaces = array( 'image' => 'http://ez.no/namespaces/ezpublish3/image/',
105 'xhtml' => 'http://ez.no/namespaces/ezpublish3/xhtml/',
106 'custom' => 'http://ez.no/namespaces/ezpublish3/custom/',
107 'tmp' => 'http://ez.no/namespaces/ezpublish3/temporary/' );
108
120 public function __construct( $validateErrorLevel = self::ERROR_NONE, $detectErrorLevel = self::ERROR_NONE, $parseLineBreaks = false,
121 $removeDefaultAttrs = false )
122 {
123 // Back-compatibility fixes:
124 if ( $detectErrorLevel === self::SHOW_SCHEMA_ERRORS )
125 {
126 $detectErrorLevel = self::ERROR_SCHEMA;
127 }
128 elseif ( $detectErrorLevel === self::SHOW_ALL_ERRORS )
129 {
130 $detectErrorLevel = self::ERROR_ALL;
131 }
132
133 if ( $validateErrorLevel === false )
134 {
135 $validateErrorLevel = self::ERROR_NONE;
136 }
137 elseif ( $validateErrorLevel === true )
138 {
139 $validateErrorLevel = $detectErrorLevel;
140 }
141
142 $this->ValidateErrorLevel = $validateErrorLevel;
143 $this->DetectErrorLevel = $detectErrorLevel;
144
145 $this->RemoveDefaultAttrs = $removeDefaultAttrs;
146 $this->ParseLineBreaks = $parseLineBreaks;
147
148 $this->XMLSchema = eZXMLSchema::instance();
149
150 $this->eZPublishVersion = eZPublishSDK::majorVersion() + eZPublishSDK::minorVersion() * 0.1;
151
152 $ini = eZINI::instance( 'ezxml.ini' );
153 if ( $ini->hasVariable( 'InputSettings', 'TrimSpaces' ) )
154 {
155 $trimSpaces = $ini->variable( 'InputSettings', 'TrimSpaces' );
156 $this->TrimSpaces = $trimSpaces == 'true' ? true : false;
157 }
158
159 if ( $ini->hasVariable( 'InputSettings', 'AllowMultipleSpaces' ) )
160 {
161 $allowMultipleSpaces = $ini->variable( 'InputSettings', 'AllowMultipleSpaces' );
162 $this->AllowMultipleSpaces = $allowMultipleSpaces == 'true' ? true : false;
163 }
164
165 if ( $ini->hasVariable( 'InputSettings', 'AllowNumericEntities' ) )
166 {
167 $allowNumericEntities = $ini->variable( 'InputSettings', 'AllowNumericEntities' );
168 $this->AllowNumericEntities = $allowNumericEntities == 'true' ? true : false;
169 }
170
171 $contentIni = eZINI::instance( 'content.ini' );
172 $useStrictHeaderRule = $contentIni->variable( 'header', 'UseStrictHeaderRule' );
173 $this->StrictHeaders = $useStrictHeaderRule == 'true' ? true : false;
174 }
175
177 function setDOMDocumentClass( $DOMDocumentClass )
178 {
179 $this->DOMDocumentClass = $DOMDocumentClass;
180 }
181
183 function setParseLineBreaks( $value )
184 {
185 $this->ParseLineBreaks = $value;
186 }
187
189 function setRemoveDefaultAttrs( $value )
190 {
191 $this->RemoveDefaultAttrs = $value;
192 }
193
195 function createRootNode()
196 {
197 if ( !$this->Document )
198 {
199 $this->Document = new $this->DOMDocumentClass( '1.0', 'utf-8' );
200 }
201
202 // Creating root section with namespaces definitions
203 $mainSection = $this->Document->createElement( 'section' );
204 $this->Document->appendChild( $mainSection );
205 foreach( array( 'image', 'xhtml', 'custom' ) as $prefix )
206 {
207 $mainSection->setAttributeNS( 'http://www.w3.org/2000/xmlns/', 'xmlns:' . $prefix, $this->Namespaces[$prefix] );
208 }
209 return $this->Document;
210 }
211
216 function process( $text, $createRootNode = true )
217 {
218 $text = str_replace( "\r", '', $text);
219 $text = str_replace( "\t", ' ', $text);
220 // replace unicode chars that will break the XML validity
221 // see http://www.w3.org/TR/REC-xml/#charsets
222 $text = preg_replace( '/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $text, -1, $count );
223 if ( $count > 0 )
224 {
225 $this->Messages[] = ezpI18n::tr(
226 'kernel/classes/datatypes/ezxmltext',
227 "%count invalid character(s) have been found and replaced by a space",
228 false,
229 array( '%count' => $count )
230 );
231 }
232 if ( !$this->ParseLineBreaks )
233 {
234 $text = str_replace( "\n", '', $text);
235 }
236
237 $this->Document = new $this->DOMDocumentClass( '1.0', 'utf-8' );
238
239 if ( $createRootNode )
240 {
241 $this->createRootNode();
242 }
243
244 // Perform pass 1
245 // Parsing the source string
246 $this->performPass1( $text );
247
248 //$this->Document->formatOutput = true;
249 $debug = eZDebugSetting::isConditionTrue( 'kernel-datatype-ezxmltext', eZDebug::LEVEL_DEBUG );
250 if ( $debug )
251 {
252 eZDebug::writeDebug( $this->Document->saveXML(), eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext', 'XML after pass 1' ) );
253 }
254
255 if ( $this->QuitProcess )
256 {
257 return false;
258 }
259
260 // Perform pass 2
261 $this->performPass2();
262
263 //$this->Document->formatOutput = true;
264 if ( $debug )
265 {
266 eZDebug::writeDebug( $this->Document->saveXML(), eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext', 'XML after pass 2' ) );
267 }
268
269 if ( $this->QuitProcess )
270 {
271 return false;
272 }
273
274 return $this->Document;
275 }
276
277 /*
278 \public
279 Pass 1: Parsing the source HTML string.
280 */
281
282 function performPass1( &$data )
283 {
284 $ret = true;
285 $pos = 0;
286
287 if ( $this->Document->documentElement )
288 {
289 do
290 {
291 $this->parseTag( $data, $pos, $this->Document->documentElement );
292 if ( $this->QuitProcess )
293 {
294 $ret = false;
295 break;
296 }
297
298 }
299 while( $pos < strlen( $data ) );
300 }
301 else
302 {
303 $tmp = null;
304 $this->parseTag( $data, $pos, $tmp );
305 if ( $this->QuitProcess )
306 {
307 $ret = false;
308 }
309 }
310 return $ret;
311 }
312
313 // The main recursive function for pass 1
314
315 function parseTag( &$data, &$pos, &$parent )
316 {
317 // Find tag, determine it's type, name and attributes.
318 $initialPos = $pos;
319
320 if ( $pos >= strlen( $data ) )
321 {
322 return true;
323 }
324 $tagBeginPos = strpos( $data, '<', $pos );
325
326 if ( $this->ParseLineBreaks )
327 {
328 // Regard line break as a start tag position
329 $lineBreakPos = strpos( $data, "\n", $pos );
330 if ( $lineBreakPos !== false )
331 {
332 $tagBeginPos = $tagBeginPos === false ? $lineBreakPos : min( $tagBeginPos, $lineBreakPos );
333 }
334 }
335
336 $tagName = '';
337 $attributes = null;
338 // If it doesn't begin with '<' then its a text node.
339 if ( $tagBeginPos != $pos || $tagBeginPos === false )
340 {
341 $pos = $initialPos;
342 $tagName = $newTagName = '#text';
343 $noChildren = true;
344
345 if ( !$tagBeginPos )
346 {
347 $tagBeginPos = strlen( $data );
348 }
349
350 $textContent = substr( $data, $pos, $tagBeginPos - $pos );
351
352 $textContent = $this->washText( $textContent );
353
354 $pos = $tagBeginPos;
355 if ( $textContent === '' )
356 {
357 return false;
358 }
359 }
360 // Process closing tag.
361 elseif ( $data[$tagBeginPos] == '<' && $tagBeginPos + 1 < strlen( $data ) &&
362 $data[$tagBeginPos + 1] == '/' )
363 {
364 $tagEndPos = strpos( $data, '>', $tagBeginPos + 1 );
365 if ( $tagEndPos === false )
366 {
367 $pos = $tagBeginPos + 1;
368
369 $this->handleError( self::ERROR_SYNTAX, ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', 'Wrong closing tag' ) );
370 return false;
371 }
372
373 $pos = $tagEndPos + 1;
374 $closedTagName = strtolower( trim( substr( $data, $tagBeginPos + 2, $tagEndPos - $tagBeginPos - 2 ) ) );
375
376 // Find matching tag in ParentStack array
377 $firstLoop = true;
378 for( $i = count( $this->ParentStack ) - 1; $i >= 0; $i-- )
379 {
380 $parentNames = $this->ParentStack[$i];
381 if ( $parentNames[0] == $closedTagName )
382 {
383 array_pop( $this->ParentStack );
384 if ( !$firstLoop )
385 {
386 $pos = $tagBeginPos;
387 return true;
388 }
389 // If newTagName was '' we don't break children loop
390 elseif ( $parentNames[1] !== '' )
391 {
392 return true;
393 }
394 else
395 {
396 return false;
397 }
398 }
399 $firstLoop = false;
400 }
401
402 $this->handleError( self::ERROR_SYNTAX, ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', 'Wrong closing tag : &lt;/%1&gt;.', false, array( $closedTagName ) ) );
403
404 return false;
405 }
406 // Insert <br/> instead of linebreaks
407 elseif ( $this->ParseLineBreaks && $data[$tagBeginPos] == "\n" )
408 {
409 $newTagName = 'br';
410 $noChildren = true;
411 $pos = $tagBeginPos + 1;
412 }
413 // Regular tag: get tag's name and attributes.
414 else
415 {
416 $tagEndPos = $this->findEndOpeningTagPosition( $data, $tagBeginPos );
417 if ( $tagEndPos === false )
418 {
419 $pos = $tagBeginPos + 1;
420
421 $this->handleError( self::ERROR_SYNTAX, ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', 'Wrong opening tag' ) );
422 return false;
423 }
424
425 $pos = $tagEndPos + 1;
426 $tagString = substr( $data, $tagBeginPos + 1, $tagEndPos - $tagBeginPos - 1 );
427 // Check for final backslash
428 $noChildren = substr( $tagString, -1, 1 ) == '/' ? true : false;
429 // Remove final backslash and spaces
430 $tagString = preg_replace( "/\s*\/$/", "", $tagString );
431
432 $firstSpacePos = strpos( $tagString, ' ' );
433 if ( $firstSpacePos === false )
434 {
435 $tagName = strtolower( trim( $tagString ) );
436 $attributeString = '';
437 }
438 else
439 {
440 $tagName = strtolower( substr( $tagString, 0, $firstSpacePos ) );
441 $attributeString = substr( $tagString, $firstSpacePos + 1 );
442 $attributeString = trim( $attributeString );
443 // Parse attribute string
444 if ( $attributeString )
445 {
446 $attributes = $this->parseAttributes( $attributeString );
447 }
448 }
449
450 // Determine tag's name
451 if ( isset( $this->InputTags[$tagName] ) )
452 {
453 $thisInputTag = $this->InputTags[$tagName];
454
455 if ( isset( $thisInputTag['name'] ) )
456 {
457 $newTagName = $thisInputTag['name'];
458 }
459 else
460 {
461 $newTagName = $this->callInputHandler( 'nameHandler', $tagName, $attributes );
462 }
463 }
464 else
465 {
466 if ( $this->XMLSchema->exists( $tagName ) )
467 {
468 $newTagName = $tagName;
469 }
470 else
471 {
472 $this->handleError( self::ERROR_SYNTAX, ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', 'Unknown tag: &lt;%1&gt;.', false, array( $tagName ) ) );
473 return false;
474 }
475 }
476
477 // Check 'noChildren' property
478 if ( isset( $thisInputTag['noChildren'] ) )
479 {
480 $noChildren = true;
481 }
482
483 $thisOutputTag = isset( $this->OutputTags[$newTagName] ) ? $this->OutputTags[$newTagName] : null;
484
485 // Implementation of 'autoCloseOn' rule ( Handling of unclosed tags, ex.: <p>, <li> )
486 if ( isset( $thisOutputTag['autoCloseOn'] ) &&
487 $parent &&
488 $parent->parentNode instanceof DOMElement &&
489 in_array( $parent->nodeName, $thisOutputTag['autoCloseOn'] ) )
490 {
491 // Wrong nesting: auto-close parent and try to re-parse this tag at higher level
492 array_pop( $this->ParentStack );
493 $pos = $tagBeginPos;
494 return true;
495 }
496
497 // Append to parent stack
498 if ( !$noChildren && $newTagName !== false )
499 {
500 $this->ParentStack[] = array( $tagName, $newTagName, $attributeString );
501 }
502
503 if ( !$newTagName )
504 {
505 // If $newTagName is an empty string then it's not a error
506 if ( $newTagName === false )
507 $this->handleError( self::ERROR_SYNTAX, ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Can't convert tag's name: &lt;%1&gt;.", false, array( $tagName ) ) );
508
509 return false;
510 }
511
512 // wordmatch.ini support
513 if ( $attributeString )
514 {
515 $attributes = $this->wordMatchSupport( $newTagName, $attributes, $attributeString );
516 }
517 }
518
519 // Create text or normal node.
520 if ( $newTagName == '#text' )
521 {
522 $element = $this->Document->createTextNode( $textContent );
523 }
524 else
525 {
526 $element = $this->Document->createElement( $newTagName );
527 }
528
529 if ( $attributes )
530 {
531 $this->setAttributes( $element, $attributes );
532 }
533
534 // Append element as a child or set it as root if there is no parent.
535 if ( $parent )
536 {
537 $parent->appendChild( $element );
538 }
539 else
540 {
541 $this->Document->appendChild( $element );
542 }
543
544 $params = array();
545 $params[] =& $data;
546 $params[] =& $pos;
547 $params[] =& $tagBeginPos;
548 $result = $this->callOutputHandler( 'parsingHandler', $element, $params );
549
550 if ( $result === false )
551 {
552 // This tag is already parsed in handler
553 if ( !$noChildren )
554 {
555 array_pop( $this->ParentStack );
556 }
557 return false;
558 }
559
560 if ( $this->QuitProcess )
561 {
562 return false;
563 }
564
565 // Process children
566 if ( !$noChildren )
567 {
568 do
569 {
570 $parseResult = $this->parseTag( $data, $pos, $element );
571 if ( $this->QuitProcess )
572 {
573 return false;
574 }
575 }
576 while( $parseResult !== true );
577 }
578
579 return false;
580 }
581
582 /*
583 Helper functions for pass 1
584 */
585
598 private function findEndOpeningTagPosition( $data, $tagBeginPos, $offset = 0 )
599 {
600 $endPos = strpos( $data, '>', $tagBeginPos + $offset );
601 if ( $endPos === false )
602 {
603 return false;
604 }
605 $tagCode = substr( $data, $tagBeginPos, $endPos - $tagBeginPos );
606 if ( strpos( $tagCode, '=' ) === false )
607 {
608 // this tag has no attribute, so the next '>' is the right one.
609 return $endPos;
610 }
611 if ( $this->isValidXmlTag( $tagCode ) )
612 {
613 return $endPos;
614 }
615 return $this->findEndOpeningTagPosition( $data, $tagBeginPos, $endPos - $tagBeginPos + 1 );
616 }
617
625 private function isValidXmlTag( $code )
626 {
627 if ( $code[strlen( $code ) - 1] !== '/' )
628 {
629 $code .= '/';
630 }
631 $code .= '>';
632 $code = '<' . str_replace(
633 array( '<', '&' ),
634 array( '&lt;', '&amp;' ),
635 substr( $code, 1 )
636 );
637 $errorHanding = libxml_use_internal_errors( true );
638 $simpleXml = simplexml_load_string( $code );
639 libxml_use_internal_errors( $errorHanding );
640 return ( $simpleXml !== false );
641 }
642
643 function parseAttributes( $attributeString )
644 {
645 $attributes = array();
646 // Valid characters for XML attributes
647 // @see http://www.w3.org/TR/xml/#NT-Name
648 $nameStartChar = ':A-Z_a-z\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\x{2FF}\\x{370}-\\x{37D}\\x{37F}-\\x{1FFF}\\x{200C}-\\x{200D}\\x{2070}-\\x{218F}\\x{2C00}-\\x{2FEF}\\x{3001}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}';
649 if (
650 preg_match_all(
651 "/\s+([$nameStartChar][$nameStartChar\-.0-9\\xB7\\x{0300}-\\x{036F}\\x{203F}-\\x{2040}]*)\s*=\s*(?:(?:\"([^\"]+?)\")|(?:'([^']+?)')|(?: *([^\"'\s]+)))/u",
652 " " . $attributeString,
653 $attributeArray,
654 PREG_SET_ORDER
655 )
656 ) {
657 foreach ( $attributeArray as $attribute )
658 {
659 // Value will always be at the last position
660 $value = trim( array_pop( $attribute ) );
661 // Value of '0' is valid ( eg. border='0' )
662 if ( $value !== '' && $value !== false && $value !== null )
663 {
664 $attributes[$attribute[1]] = $value;
665 }
666 }
667 }
668
669 return $attributes;
670 }
671
672 function setAttributes( $element, $attributes )
673 {
674 $thisOutputTag = $this->OutputTags[$element->nodeName];
675
676 foreach( $attributes as $key => $value )
677 {
678 // Convert attribute names
679 if ( isset( $thisOutputTag['attributes'] ) &&
680 isset( $thisOutputTag['attributes'][$key] ) )
681 {
682 $qualifiedName = $thisOutputTag['attributes'][$key];
683 }
684 else
685 {
686 $qualifiedName = $key;
687 }
688
689 // Filter classes
690 if ( $qualifiedName == 'class' )
691 {
692 $classesList = $this->XMLSchema->getClassesList( $element->nodeName );
693 if ( !in_array( $value, $classesList ) )
694 {
695 $this->handleError( self::ERROR_DATA,
696 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Class '%1' is not allowed for element &lt;%2&gt; (check content.ini).",
697 false, array( $value, $element->nodeName ) ) );
698 continue;
699 }
700 }
701
702 // Create attribute nodes
703 if ( $qualifiedName )
704 {
705 if ( strpos( $qualifiedName, ':' ) )
706 {
707 list( $prefix, $name ) = explode( ':', $qualifiedName );
708 if ( isset( $this->Namespaces[$prefix] ) )
709 {
710 $URI = $this->Namespaces[$prefix];
711 $element->setAttributeNS( $URI, $qualifiedName, htmlspecialchars_decode( $value ) );
712 }
713 else
714 {
715 eZDebug::writeWarning( "No namespace defined for prefix '$prefix'.", 'eZXML input parser' );
716 }
717 }
718 else
719 {
720 $element->setAttribute( $qualifiedName, htmlspecialchars_decode( $value ) );
721 }
722 }
723 }
724
725 // Check for required attrs are present
726 if ( isset( $this->OutputTags[$element->nodeName]['requiredInputAttributes'] ) )
727 {
728 foreach( $this->OutputTags[$element->nodeName]['requiredInputAttributes'] as $reqAttrName )
729 {
730 $presented = false;
731 foreach( $attributes as $key => $value )
732 {
733 if ( $key == $reqAttrName )
734 {
735 $presented = true;
736 break;
737 }
738 }
739 if ( !$presented )
740 {
741 $this->handleError( self::ERROR_SCHEMA,
742 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Required attribute '%1' is not presented in tag &lt;%2&gt;.",
743 false, array( $reqAttrName, $element->nodeName ) ) );
744 }
745 }
746 }
747 }
748
749 function washText( $textContent )
750 {
751 $textContent = $this->entitiesDecode( $textContent );
752
753 if ( !$this->AllowNumericEntities )
754 {
755 $textContent = $this->convertNumericEntities( $textContent );
756 }
757
758 if ( !$this->AllowMultipleSpaces )
759 {
760 $textContent = preg_replace( "/ {2,}/", " ", $textContent );
761 }
762
763 return $textContent;
764 }
765
766 function entitiesDecode( $text )
767 {
768 $text = str_replace( '&#039;', "'", $text );
769
770 $text = str_replace( '&gt;', '>', $text );
771 $text = str_replace( '&lt;', '<', $text );
772 $text = str_replace( '&apos;', "'", $text );
773 $text = str_replace( '&quot;', '"', $text );
774 $text = str_replace( '&amp;', '&', $text );
775 return $text;
776 }
777
778 function convertNumericEntities( $text )
779 {
780 if ( strlen( $text ) < 4 )
781 {
782 return $text;
783 }
784 // Convert other HTML entities to the current charset characters.
785 $convmap = array( 0x0, 0x2FFFF, 0, 0xFFFF );
786 return mb_decode_numericentity( $text, $convmap, 'UTF-8' );
787 }
788
792 protected function wordMatchSupport( $newTagName, $attributes, $attributeString )
793 {
794 $ini = eZINI::instance( 'wordmatch.ini' );
795 if ( $ini->hasVariable( $newTagName, 'MatchString' ) )
796 {
797 $matchArray = $ini->variable( $newTagName, 'MatchString' );
798 if ( $matchArray )
799 {
800 foreach ( array_keys( $matchArray ) as $key )
801 {
802 $matchString = $matchArray[$key];
803 if ( preg_match( "/$matchString/i", $attributeString ) )
804 {
805 $attributes['class'] = $key;
806 unset( $attributes['style'] );
807 }
808 }
809 }
810 }
811 return $attributes;
812 }
813
814
820 function performPass2()
821 {
822 $tmp = null;
823
824 $this->processSubtree( $this->Document->documentElement, $tmp );
825 }
826
827 // main recursive function for pass 2
828
829 function processSubtree( $element, &$lastHandlerResult )
830 {
831 $ret = null;
832 $tmp = null;
833
834 // Call "Init handler"
835 $this->callOutputHandler( 'initHandler', $element, $tmp );
836
837 $debug = eZDebugSetting::isConditionTrue( 'kernel-datatype-ezxmltext', eZDebug::LEVEL_DEBUG );
838
839 // Process children
840 if ( $element->hasChildNodes() )
841 {
842 // Make another copy of children to save primary structure
843 $childNodes = $element->childNodes;
844 $childrenCount = $childNodes->length;
845
846 // we can not loop directly over the childNodes property, because this will change while we are working on it's parent's children
847 $children = array();
848 foreach ( $childNodes as $childNode )
849 {
850 $children[] = $childNode;
851 }
852
853 $lastResult = null;
854 $newElements = array();
855 foreach ( $children as $child )
856 {
857 if ( $debug )
858 {
859 eZDebug::writeDebug( 'processing children, current child: ' . $child->nodeName, eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext', __METHOD__ ) );
860 }
861
862 $childReturn = $this->processSubtree( $child, $lastResult );
863
864 unset( $lastResult );
865 if ( isset( $childReturn['result'] ) )
866 {
867 if ( $debug )
868 {
869 eZDebug::writeDebug( 'return result is set for child ' . $child->nodeName, eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext', __METHOD__ ) );
870 }
871
872 $lastResult = $childReturn['result'];
873 }
874
875 if ( isset( $childReturn['new_elements'] ) )
876 {
877 $newElements = array_merge( $newElements, $childReturn['new_elements'] );
878 }
879
880 if ( $this->QuitProcess )
881 {
882 return $ret;
883 }
884 }
885
886 if ( $debug )
887 {
888 eZDebug::writeDebug( $this->Document->saveXML(),
889 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
890 'XML before processNewElements for element ' . $element->nodeName ) );
891 }
892
893 // process elements created in children handlers
894 $this->processNewElements( $newElements );
895
896 if ( $debug )
897 {
898 eZDebug::writeDebug( $this->Document->saveXML(),
899 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
900 'XML after processNewElements for element ' . $element->nodeName ) );
901 }
902 }
903
904 // Call "Structure handler"
905 if ( $debug )
906 {
907 eZDebug::writeDebug( $this->Document->saveXML(),
908 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
909 'XML before callOutputHandler structHandler for element ' . $element->nodeName ) );
910 }
911
912 $ret = $this->callOutputHandler( 'structHandler', $element, $lastHandlerResult );
913
914 if ( $debug )
915 {
916 eZDebug::writeDebug( $this->Document->saveXML(),
917 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
918 'XML after callOutputHandler structHandler for element ' . $element->nodeName ) );
919 eZDebug::writeDebug( $ret,
920 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
921 'return value of callOutputHandler structHandler for element ' . $element->nodeName ) );
922 }
923
924 // Process by schema (check if element is allowed to exist)
925 if ( !$this->processBySchemaPresence( $element ) )
926 {
927 if ( $debug )
928 {
929 eZDebug::writeDebug( $this->Document->saveXML(),
930 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
931 'XML after failed processBySchemaPresence for element ' . $element->nodeName ) );
932 }
933 return $ret;
934 }
935
936 if ( $debug )
937 {
938 eZDebug::writeDebug( $this->Document->saveXML(),
939 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
940 'XML after processBySchemaPresence for element ' . $element->nodeName ) );
941 }
942
943 // Process by schema (check place in the tree)
944 if ( !$this->processBySchemaTree( $element ) )
945 {
946 if ( $debug )
947 {
948 eZDebug::writeDebug( $this->Document->saveXML(),
949 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
950 'XML after failed processBySchemaTree for element ' . $element->nodeName ) );
951 }
952 return $ret;
953 }
954
955 if ( $debug )
956 {
957 eZDebug::writeDebug( $this->Document->saveXML(),
958 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
959 'XML after processBySchemaTree for element ' . $element->nodeName ) );
960 }
961
962
963 $tmp = null;
964 // Call "Publish handler"
965 $this->callOutputHandler( 'publishHandler', $element, $tmp );
966
967 // Process attributes according to the schema
968 if ( $element->hasAttributes() )
969 {
970 if ( !$this->XMLSchema->hasAttributes( $element ) )
971 {
972 eZXMLInputParser::removeAllAttributes( $element );
973 }
974 else
975 {
976 $this->processAttributesBySchema( $element );
977 }
978 }
979 return $ret;
980 }
981 /*
982 Helper functions for pass 2
983 */
984
988 function removeAllAttributes( DOMElement $element )
989 {
990 $attribs = $element->attributes;
991 for ( $i = $attribs->length - 1; $i >= 0; $i-- )
992 {
993 $element->removeAttributeNode( $attribs->item( $i ) );
994 }
995 }
996
997 // Check if the element is allowed to exist in this document and remove it if not.
998 function processBySchemaPresence( $element )
999 {
1000 $parent = $element->parentNode;
1001 if ( $parent instanceof DOMElement )
1002 {
1003 // If this is a foreign element, remove it
1004 if ( !$this->XMLSchema->exists( $element ) )
1005 {
1006 if ( $element->nodeName == 'custom' )
1007 {
1008 $this->handleError( self::ERROR_SCHEMA,
1009 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Custom tag '%1' is not allowed.",
1010 false, array( $element->getAttribute( 'name' ) ) ) );
1011 }
1012 $element = $parent->removeChild( $element );
1013 return false;
1014 }
1015
1016 // Delete if children required and no children
1017 // If this is an auto-added element, then do not throw error
1018
1019 if ( $element->nodeType == XML_ELEMENT_NODE && ( $this->XMLSchema->childrenRequired( $element ) || $element->getAttribute( 'children_required' ) )
1020 && !$element->hasChildNodes() )
1021 {
1022 $element = $parent->removeChild( $element );
1023 if ( !$element->getAttributeNS( 'http://ez.no/namespaces/ezpublish3/temporary/', 'new-element' ) )
1024 {
1025 $this->handleError( self::ERROR_SCHEMA, ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "&lt;%1&gt; tag can't be empty.",
1026 false, array( $element->nodeName ) ) );
1027 return false;
1028 }
1029 }
1030 }
1031 // TODO: break processing of any node that doesn't have parent
1032 // and is not a root node.
1033 elseif ( $element->nodeName != 'section' )
1034 {
1035 return false;
1036 }
1037 return true;
1038 }
1039
1040 // Check that element has a correct position in the tree and fix it if not.
1041 function processBySchemaTree( $element )
1042 {
1043 $parent = $element->parentNode;
1044
1045 if ( $parent instanceof DOMElement )
1046 {
1047 $schemaCheckResult = $this->XMLSchema->check( $parent, $element );
1048 if ( !$schemaCheckResult )
1049 {
1050 if ( $schemaCheckResult === false )
1051 {
1052 // Remove indenting spaces
1053 if ( $element->nodeType == XML_TEXT_NODE && !trim( $element->textContent ) )
1054 {
1055 $element = $parent->removeChild( $element );
1056 return false;
1057 }
1058
1059 $elementName = $element->nodeType == XML_ELEMENT_NODE ? '&lt;' . $element->nodeName . '&gt;' : $element->nodeName;
1060 $this->handleError( self::ERROR_SCHEMA, ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "%1 is not allowed to be a child of &lt;%2&gt;.",
1061 false, array( $elementName, $parent->nodeName ) ) );
1062 }
1063 $this->fixSubtree( $element, $element );
1064 return false;
1065 }
1066 }
1067 // TODO: break processing of any node that doesn't have parent
1068 // and is not a root node.
1069 elseif ( $element->nodeName != 'section' )
1070 {
1071 return false;
1072 }
1073 return true;
1074 }
1075
1076 // Remove only nodes that don't match schema (recursively)
1077 function fixSubtree( $element, $mainChild )
1078 {
1079 $parent = $element->parentNode;
1080 $mainParent = $mainChild->parentNode;
1081 while ( $element->hasChildNodes() )
1082 {
1083 $child = $element->firstChild;
1084
1085 $child = $element->removeChild( $child );
1086 $child = $mainParent->insertBefore( $child, $mainChild );
1087
1088 if ( !$this->XMLSchema->check( $mainParent, $child ) )
1089 {
1090 $this->fixSubtree( $child, $mainChild );
1091 }
1092 }
1093 $parent->removeChild( $element );
1094 }
1095
1096 function processAttributesBySchema( $element )
1097 {
1098 // Remove attributes that don't match schema
1099 $schemaAttributes = $this->XMLSchema->attributes( $element );
1100 $schemaCustomAttributes = $this->XMLSchema->customAttributes( $element );
1101
1102 $attributes = $element->attributes;
1103
1104 for ( $i = $attributes->length - 1; $i >=0; $i-- )
1105 {
1106 $attr = $attributes->item( $i );
1107 if ( $attr->prefix == 'tmp' )
1108 {
1109 $element->removeAttributeNode( $attr );
1110 continue;
1111 }
1112
1113 $allowed = false;
1114 $removeAttr = false;
1115
1116 $fullName = $attr->prefix ? $attr->prefix . ':' . $attr->localName : $attr->nodeName;
1117
1118 // check for allowed custom attributes (3.9)
1119 if ( $attr->prefix == 'custom' && in_array( $attr->localName, $schemaCustomAttributes ) )
1120 {
1121 $allowed = true;
1122 }
1123 else
1124 {
1125 if ( in_array( $fullName, $schemaAttributes ) )
1126 {
1127 $allowed = true;
1128 }
1129 elseif ( in_array( $fullName, $schemaCustomAttributes ) )
1130 {
1131 // add 'custom' prefix if it is not given
1132 $allowed = true;
1133 $removeAttr = true;
1134 $element->setAttributeNS( $this->Namespaces['custom'], 'custom:' . $fullName, $attr->value );
1135 }
1136 }
1137
1138 if ( !$allowed )
1139 {
1140 $removeAttr = true;
1141 $this->handleError( self::ERROR_SCHEMA,
1142 ezpI18n::tr( 'kernel/classes/datatypes/ezxmltext', "Attribute '%1' is not allowed in &lt;%2&gt; element.",
1143 false, array( $fullName, $element->nodeName ) ) );
1144 }
1145 elseif ( $this->RemoveDefaultAttrs )
1146 {
1147 // Remove attributes having default values
1148 $default = $this->XMLSchema->attrDefaultValue( $element->nodeName, $fullName );
1149 if ( $attr->value == $default )
1150 {
1151 $removeAttr = true;
1152 }
1153 }
1154
1155 if ( $removeAttr )
1156 {
1157 $element->removeAttributeNode( $attr );
1158 }
1159 }
1160 }
1161
1162 function callInputHandler( $handlerName, $tagName, &$attributes )
1163 {
1164 $result = null;
1165 $thisInputTag = $this->InputTags[$tagName];
1166 if ( isset( $thisInputTag[$handlerName] ) )
1167 {
1168 if ( is_callable( array( $this, $thisInputTag[$handlerName] ) ) )
1169 {
1170 $result = call_user_func_array( array( $this, $thisInputTag[$handlerName] ),
1171 array( $tagName, &$attributes ) );
1172 }
1173 else
1174 {
1175 eZDebug::writeWarning( "'$handlerName' input handler for tag <$tagName> doesn't exist: '" . $thisInputTag[$handlerName] . "'.", 'eZXML input parser' );
1176 }
1177 }
1178 return $result;
1179 }
1180
1181 function callOutputHandler( $handlerName, $element, &$params )
1182 {
1183 $result = null;
1184 $thisOutputTag = $this->OutputTags[$element->nodeName];
1185 if ( isset( $thisOutputTag[$handlerName] ) )
1186 {
1187 if ( is_callable( array( $this, $thisOutputTag[$handlerName] ) ) )
1188 {
1189 $result = call_user_func_array( array( $this, $thisOutputTag[$handlerName] ),
1190 array( $element, &$params ) );
1191 }
1192 else
1193 {
1194 eZDebug::writeWarning( "'$handlerName' output handler for tag <$element->nodeName> doesn't exist: '" . $thisOutputTag[$handlerName] . "'.", 'eZXML input parser' );
1195 }
1196 }
1197
1198 return $result;
1199 }
1200
1201 // Creates new element and adds it to array for further post-processing.
1202 // Use this function if you need to process newly created element (check it by schema
1203 // and call 'structure' and 'publish' handlers)
1204 function createAndPublishElement( $elementName, &$ret )
1205 {
1206 $element = $this->Document->createElement( $elementName );
1207 $element->setAttributeNS( 'http://ez.no/namespaces/ezpublish3/temporary/', 'tmp:new-element', 'true' );
1208
1209 if ( !isset( $ret['new_elements'] ) )
1210 {
1211 $ret['new_elements'] = array();
1212 }
1213
1214 $ret['new_elements'][] = $element;
1215 return $element;
1216 }
1217
1218 function processNewElements( $createdElements )
1219 {
1220 $debug = eZDebugSetting::isConditionTrue( 'kernel-datatype-ezxmltext', eZDebug::LEVEL_DEBUG );
1221 // Call handlers for newly created elements
1222 foreach ( $createdElements as $element )
1223 {
1224 if ( $debug )
1225 {
1226 eZDebug::writeDebug( 'processing new element ' . $element->nodeName, eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext' ) );
1227 }
1228
1229 $tmp = null;
1230 if ( !$this->processBySchemaPresence( $element ) )
1231 {
1232 if ( $debug )
1233 {
1234 eZDebug::writeDebug( $this->Document->saveXML(),
1235 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
1236 'xml string after failed processBySchemaPresence for new element ' . $element->nodeName ) );
1237 }
1238 continue;
1239 }
1240
1241 if ( $debug )
1242 {
1243 eZDebug::writeDebug( $this->Document->saveXML(),
1244 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
1245 'xml string after processBySchemaPresence for new element ' . $element->nodeName ) );
1246 }
1247
1248
1249 // Call "Structure handler"
1250 $this->callOutputHandler( 'structHandler', $element, $tmp );
1251
1252 if ( !$this->processBySchemaTree( $element ) )
1253 {
1254 if ( $debug )
1255 {
1256 eZDebug::writeDebug( $this->Document->saveXML(),
1257 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
1258 'xml string after failed processBySchemaTree for new element ' . $element->nodeName ) );
1259 }
1260 continue;
1261 }
1262
1263 if ( $debug )
1264 {
1265 eZDebug::writeDebug( $this->Document->saveXML(),
1266 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
1267 'xml string after processBySchemaTree for new element ' . $element->nodeName ) );
1268 }
1269
1270
1271 $tmp2 = null;
1272 // Call "Publish handler"
1273 $this->callOutputHandler( 'publishHandler', $element, $tmp2 );
1274
1275 if ( $debug )
1276 {
1277 eZDebug::writeDebug( $this->Document->saveXML(),
1278 eZDebugSetting::changeLabel( 'kernel-datatype-ezxmltext',
1279 'xml string after callOutputHandler publishHandler for new element ' . $element->nodeName ) );
1280 }
1281
1282 // Process attributes according to the schema
1283 if( $element->hasAttributes() )
1284 {
1285 if ( !$this->XMLSchema->hasAttributes( $element ) )
1286 {
1287 eZXMLInputParser::removeAllAttributes( $element );
1288 }
1289 else
1290 {
1291 $this->processAttributesBySchema( $element );
1292 }
1293 }
1294 }
1295 }
1296
1298 function getMessages()
1299 {
1300 return $this->Messages;
1301 }
1302
1304 function isValid()
1305 {
1306 return $this->IsInputValid;
1307 }
1308
1309 function handleError( $type, $message )
1310 {
1311 if ( $type & $this->DetectErrorLevel )
1312 {
1313 $this->IsInputValid = false;
1314 if ( $message )
1315 {
1316 $this->Messages[] = $message;
1317 }
1318 }
1319
1320 if ( $type & $this->ValidateErrorLevel )
1321 {
1322 $this->IsInputValid = false;
1323 $this->QuitProcess = true;
1324 }
1325 }
1326
1327 public $DOMDocumentClass = 'DOMDocument';
1328
1329 public $XMLSchema;
1330 public $Document = null;
1331 public $Messages = array();
1332 public $eZPublishVersion;
1333
1334 public $ParentStack = array();
1335
1336 public $ValidateErrorLevel;
1337 public $DetectErrorLevel;
1338
1339 public $IsInputValid = true;
1340 public $QuitProcess = false;
1341
1342 // options that depend on settings
1343 public $TrimSpaces = true;
1344 public $AllowMultipleSpaces = false;
1345 public $AllowNumericEntities = false;
1346 public $StrictHeaders = false;
1347
1348 // options that depend on parameters passed
1349 public $ParseLineBreaks = false;
1350 public $RemoveDefaultAttrs = false;
1351 }
1352 ?>
eZDebugSetting\isConditionTrue
static isConditionTrue( $conditionName, $messageType)
Definition: ezdebugsetting.php:47
eZDebugSetting\changeLabel
static changeLabel( $conditionName, $label='')
Definition: ezdebugsetting.php:70
eZDebug\writeDebug
static writeDebug( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:588
eZDebug\writeWarning
static writeWarning( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:502
eZDebug\LEVEL_DEBUG
const LEVEL_DEBUG
Definition: ezdebug.php:63
eZXMLInputParser
Definition: ezxmlinputparser.php:25
eZXMLInputParser\$InputTags
$InputTags
Definition: ezxmlinputparser.php:66
eZXMLInputParser\ERROR_NONE
const ERROR_NONE
Use these constants for error types.
Definition: ezxmlinputparser.php:32
eZXMLInputParser\setRemoveDefaultAttrs
setRemoveDefaultAttrs( $value)
Definition: ezxmlinputparser.php:189
eZXMLInputParser\processNewElements
processNewElements( $createdElements)
Definition: ezxmlinputparser.php:1218
eZXMLInputParser\SHOW_ALL_ERRORS
const SHOW_ALL_ERRORS
Definition: ezxmlinputparser.php:29
eZXMLInputParser\$AllowNumericEntities
$AllowNumericEntities
Definition: ezxmlinputparser.php:1345
eZXMLInputParser\__construct
__construct( $validateErrorLevel=self::ERROR_NONE, $detectErrorLevel=self::ERROR_NONE, $parseLineBreaks=false, $removeDefaultAttrs=false)
Definition: ezxmlinputparser.php:120
eZXMLInputParser\$TrimSpaces
$TrimSpaces
Definition: ezxmlinputparser.php:1343
eZXMLInputParser\parseAttributes
parseAttributes( $attributeString)
Definition: ezxmlinputparser.php:643
eZXMLInputParser\ERROR_SYNTAX
const ERROR_SYNTAX
Definition: ezxmlinputparser.php:33
eZXMLInputParser\$DetectErrorLevel
$DetectErrorLevel
Definition: ezxmlinputparser.php:1337
eZXMLInputParser\performPass2
performPass2()
Definition: ezxmlinputparser.php:820
eZXMLInputParser\callInputHandler
callInputHandler( $handlerName, $tagName, &$attributes)
Definition: ezxmlinputparser.php:1162
eZXMLInputParser\SHOW_SCHEMA_ERRORS
const SHOW_SCHEMA_ERRORS
Definition: ezxmlinputparser.php:28
eZXMLInputParser\processBySchemaPresence
processBySchemaPresence( $element)
Definition: ezxmlinputparser.php:998
eZXMLInputParser\processAttributesBySchema
processAttributesBySchema( $element)
Definition: ezxmlinputparser.php:1096
eZXMLInputParser\isValid
isValid()
Definition: ezxmlinputparser.php:1304
eZXMLInputParser\ERROR_SCHEMA
const ERROR_SCHEMA
Definition: ezxmlinputparser.php:34
eZXMLInputParser\$ParentStack
$ParentStack
Definition: ezxmlinputparser.php:1334
eZXMLInputParser\entitiesDecode
entitiesDecode( $text)
Definition: ezxmlinputparser.php:766
eZXMLInputParser\$RemoveDefaultAttrs
$RemoveDefaultAttrs
Definition: ezxmlinputparser.php:1350
eZXMLInputParser\callOutputHandler
callOutputHandler( $handlerName, $element, &$params)
Definition: ezxmlinputparser.php:1181
eZXMLInputParser\createRootNode
createRootNode()
Definition: ezxmlinputparser.php:195
eZXMLInputParser\washText
washText( $textContent)
Definition: ezxmlinputparser.php:749
eZXMLInputParser\setDOMDocumentClass
setDOMDocumentClass( $DOMDocumentClass)
Definition: ezxmlinputparser.php:177
eZXMLInputParser\$StrictHeaders
$StrictHeaders
Definition: ezxmlinputparser.php:1346
eZXMLInputParser\processBySchemaTree
processBySchemaTree( $element)
Definition: ezxmlinputparser.php:1041
eZXMLInputParser\$QuitProcess
$QuitProcess
Definition: ezxmlinputparser.php:1340
eZXMLInputParser\$Document
$Document
Definition: ezxmlinputparser.php:1330
eZXMLInputParser\$IsInputValid
$IsInputValid
Definition: ezxmlinputparser.php:1339
eZXMLInputParser\setAttributes
setAttributes( $element, $attributes)
Definition: ezxmlinputparser.php:672
eZXMLInputParser\$XMLSchema
$XMLSchema
Definition: ezxmlinputparser.php:1329
eZXMLInputParser\$ParseLineBreaks
$ParseLineBreaks
Definition: ezxmlinputparser.php:1349
eZXMLInputParser\process
process( $text, $createRootNode=true)
Definition: ezxmlinputparser.php:216
eZXMLInputParser\handleError
handleError( $type, $message)
Definition: ezxmlinputparser.php:1309
eZXMLInputParser\performPass1
performPass1(&$data)
Definition: ezxmlinputparser.php:282
eZXMLInputParser\setParseLineBreaks
setParseLineBreaks( $value)
Definition: ezxmlinputparser.php:183
eZXMLInputParser\createAndPublishElement
createAndPublishElement( $elementName, &$ret)
Definition: ezxmlinputparser.php:1204
eZXMLInputParser\ERROR_ALL
const ERROR_ALL
Definition: ezxmlinputparser.php:36
eZXMLInputParser\fixSubtree
fixSubtree( $element, $mainChild)
Definition: ezxmlinputparser.php:1077
eZXMLInputParser\removeAllAttributes
removeAllAttributes(DOMElement $element)
Definition: ezxmlinputparser.php:988
eZXMLInputParser\getMessages
getMessages()
Definition: ezxmlinputparser.php:1298
eZXMLInputParser\$Namespaces
$Namespaces
Definition: ezxmlinputparser.php:104
eZXMLInputParser\processSubtree
processSubtree( $element, &$lastHandlerResult)
Definition: ezxmlinputparser.php:829
eZXMLInputParser\$AllowMultipleSpaces
$AllowMultipleSpaces
Definition: ezxmlinputparser.php:1344
eZXMLInputParser\SHOW_NO_ERRORS
const SHOW_NO_ERRORS
Definition: ezxmlinputparser.php:27
eZXMLInputParser\convertNumericEntities
convertNumericEntities( $text)
Definition: ezxmlinputparser.php:778
eZXMLInputParser\wordMatchSupport
wordMatchSupport( $newTagName, $attributes, $attributeString)
Definition: ezxmlinputparser.php:792
eZXMLInputParser\findEndOpeningTagPosition
findEndOpeningTagPosition( $data, $tagBeginPos, $offset=0)
Definition: ezxmlinputparser.php:598
eZXMLInputParser\$ValidateErrorLevel
$ValidateErrorLevel
Definition: ezxmlinputparser.php:1336
eZXMLInputParser\$OutputTags
$OutputTags
Definition: ezxmlinputparser.php:102
eZXMLInputParser\$DOMDocumentClass
$DOMDocumentClass
Definition: ezxmlinputparser.php:1327
eZXMLInputParser\$Messages
$Messages
Definition: ezxmlinputparser.php:1331
eZXMLInputParser\isValidXmlTag
isValidXmlTag( $code)
Definition: ezxmlinputparser.php:625
eZXMLInputParser\parseTag
parseTag(&$data, &$pos, &$parent)
Definition: ezxmlinputparser.php:315
eZXMLInputParser\ERROR_DATA
const ERROR_DATA
Definition: ezxmlinputparser.php:35
eZXMLInputParser\$eZPublishVersion
$eZPublishVersion
Definition: ezxmlinputparser.php:1332
eZXMLSchema\instance
static instance()
Definition: ezxmlschema.php:223
ezpI18n\tr
static tr( $context, $source, $comment=null, $arguments=null)
Definition: ezpi18n.php:86
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.