function MsExcel_ConvertToRelative_Item(&$Txt, &$Loc, $Tag, $Att, $IsRow)
 {
     // convert tags $Tag which have a position (defined with attribute $Att) into relatives tags without attribute $Att. Missing tags are added as empty tags.
     $item_num = 0;
     $tag_len = strlen($Tag);
     $missing = '<' . $Tag . '/>';
     $closing = '</' . $Tag . '>';
     $p = 0;
     while (($p = clsTinyButStrong::f_Xml_FindTagStart($Txt, $Tag, true, $p, true, true)) !== false) {
         $Loc->PrmPos = array();
         $Loc->PrmLst = array();
         $p2 = $p + $tag_len + 2;
         // count the char '<' before and the char ' ' after
         $PosEnd = strpos($Txt, '>', $p2);
         clsTinyButStrong::f_Loc_PrmRead($Txt, $p2, true, '\'"', '<', '>', $Loc, $PosEnd, true);
         // read parameters
         if (isset($Loc->PrmPos[$Att])) {
             // attribute found
             $r = $Loc->PrmLst[$Att];
             if ($IsRow) {
                 $r = intval($r);
             } else {
                 $r = $this->Misc_ColNum($r, false);
             }
             $missing_nbr = $r - $item_num - 1;
             if ($missing_nbr < 0) {
                 return $this->RaiseError('(Excel Consistency) error in counting items <' . $Tag . '>, found number ' . $r . ', previous was ' . $item_num);
             } else {
                 // delete the $Att attribute
                 $pp = $Loc->PrmPos[$Att];
                 $pp[3]--;
                 //while ($Txt[$pp[3]]===' ') $pp[3]--; // external end of the attribute, may has an extra spaces
                 $x_p = $pp[0] - 1;
                 // we take out the space
                 $x_len = $pp[3] - $x_p + 1;
                 $Txt = substr_replace($Txt, '', $x_p, $x_len);
                 $PosEnd = $PosEnd - $x_len;
                 // If it's a cell, we look if it's a good idea to replace the shared string
                 if (!$IsRow && isset($Loc->PrmPos['t']) && $Loc->PrmLst['t'] === 's') {
                     $this->MsExcel_ReplaceString($Txt, $p, $PosEnd);
                 }
                 // add missing items before the current item
                 if ($missing_nbr > 0) {
                     $x = str_repeat($missing, $missing_nbr);
                     $x_len = strlen($x);
                     $Txt = substr_replace($Txt, $x, $p, 0);
                     $PosEnd = $PosEnd + $x_len;
                     $x = '';
                     // empty the memory
                 }
             }
             $item_num = $r;
         } else {
             // nothing to change the item is already relative
             $item_num++;
         }
         if ($IsRow && $Txt[$PosEnd - 1] !== '/') {
             // It's a row item that may contain columns
             $x_p = strpos($Txt, $closing, $PosEnd);
             if ($x_p === false) {
                 return $this->RaiseError('(Excel Consistency) closing row tag is not found.');
             }
             $x_len0 = $x_p - $PosEnd - 1;
             $x = substr($Txt, $PosEnd + 1, $x_len0);
             $this->MsExcel_ConvertToRelative_Item($x, $Loc, 'c', 'r', false);
             $Txt = substr_replace($Txt, $x, $PosEnd + 1, $x_len0);
             $x_len = strlen($x);
             $p = $x_p + $x_len - $x_len0;
         } else {
             $p = $PosEnd;
         }
     }
 }
 static function f_Xml_FindTag(&$Txt, $Tag, $Opening, $PosBeg, $Forward, $LevelStop, $WithPrm, $WithPos = false)
 {
     /* This function is a smart solution to find an XML tag.
     It allows to ignore full opening/closing couple of tags that could be inserted before the searched tag.
     It allows also to pass a number of encapsulations.
     To ignore encapsulation and opengin/closing just set $LevelStop=false.
     */
     if ($Tag === '_') {
         // New line
         $p = clsTinyButStrong::f_Xml_FindNewLine($Txt, $PosBeg, $Forward, $LevelStop !== 0);
         $Loc = new clsTbsLocator();
         $Loc->PosBeg = $Forward ? $PosBeg : $p;
         $Loc->PosEnd = $Forward ? $p : $PosBeg;
         $Loc->RightLevel = 0;
         return $Loc;
     }
     $Pos = $PosBeg + ($Forward ? -1 : +1);
     $TagIsOpening = false;
     $TagClosing = '/' . $Tag;
     $LevelNum = 0;
     $TagOk = false;
     $PosEnd = false;
     $TagL = strlen($Tag);
     $TagClosingL = strlen($TagClosing);
     $RightLevel = 0;
     do {
         // Look for the next tag def
         if ($Forward) {
             $Pos = strpos($Txt, '<', $Pos + 1);
         } else {
             if ($Pos <= 0) {
                 $Pos = false;
             } else {
                 $Pos = strrpos(substr($Txt, 0, $Pos - 1), '<');
                 // strrpos() syntax compatible with PHP 4
             }
         }
         if ($Pos !== false) {
             // Check the name of the tag
             if (strcasecmp(substr($Txt, $Pos + 1, $TagL), $Tag) == 0) {
                 $PosX = $Pos + 1 + $TagL;
                 // The next char
                 $TagOk = true;
                 $TagIsOpening = true;
             } elseif (strcasecmp(substr($Txt, $Pos + 1, $TagClosingL), $TagClosing) == 0) {
                 $PosX = $Pos + 1 + $TagClosingL;
                 // The next char
                 $TagOk = true;
                 $TagIsOpening = false;
             }
             if ($TagOk) {
                 // Check the next char
                 $x = $Txt[$PosX];
                 if ($x === ' ' or $x === "\r" or $x === "\n" or $x === '>' or $Tag === '/' or $Tag === '') {
                     // Check the encapsulation count
                     if ($LevelStop === false) {
                         // No encaplusation check
                         if ($TagIsOpening !== $Opening) {
                             $TagOk = false;
                         }
                     } else {
                         // Count the number of level
                         if ($TagIsOpening) {
                             $PosEnd = strpos($Txt, '>', $PosX);
                             if ($PosEnd !== false) {
                                 if ($Txt[$PosEnd - 1] === '/') {
                                     if ($Pos < $PosBeg and $PosEnd > $PosBeg) {
                                         $RightLevel = 1;
                                         $LevelNum++;
                                     }
                                 } else {
                                     $LevelNum++;
                                 }
                             }
                         } else {
                             $LevelNum--;
                         }
                         // Check if it's the expected level
                         if ($LevelNum != $LevelStop) {
                             $TagOk = false;
                             $PosEnd = false;
                         }
                     }
                 } else {
                     $TagOk = false;
                 }
             }
             //--> if ($TagOk)
         }
     } while ($Pos !== false and $TagOk === false);
     // Search for the end of the tag
     if ($TagOk) {
         $Loc = new clsTbsLocator();
         if ($WithPrm) {
             clsTinyButStrong::f_Loc_PrmRead($Txt, $PosX, true, '\'"', '<', '>', $Loc, $PosEnd, $WithPos);
         } elseif ($PosEnd === false) {
             $PosEnd = strpos($Txt, '>', $PosX);
             if ($PosEnd === false) {
                 $TagOk = false;
             }
         }
     }
     // Result
     if ($TagOk) {
         $Loc->PosBeg = $Pos;
         $Loc->PosEnd = $PosEnd;
         $Loc->RightLevel = $RightLevel;
         return $Loc;
     } else {
         return false;
     }
 }
Exemple #3
0
function f_Xml_FindTag(&$Txt,$Tag,$Opening,$PosBeg,$Forward,$LevelStop,$WithPrm) {
/* This function is a smarter issue to find an HTML tag.
It enables to ignore full opening/closing couple of tag that could be inserted before the searched tag.
It also enables to pass a number of encapsulations.
To ignore encapsulation and opengin/closing just set $LevelStop=false.
*/

	if ($Tag==='_') { // New line
		$p = clsTinyButStrong::f_Xml_FindNewLine($Txt,$PosBeg,$Forward,($LevelStop!==0));
		$Loc = new clsTbsLocator;
		$Loc->PosBeg = ($Forward) ? $PosBeg : $p;
		$Loc->PosEnd = ($Forward) ? $p : $PosBeg;
		return $Loc;
	}

	$Pos = $PosBeg + (($Forward) ? -1 : +1);
	$TagIsOpening = false;
	$TagClosing = '/'.$Tag;
	$LevelNum = 0;
	$TagOk = false;

	do {

		// Look for the next tag def
		if ($Forward) {
			$Pos = strpos($Txt,'<',$Pos+1);
		} else {
			if ($Pos<=0) {
				$Pos = false;
			} else {
				$Pos = strrpos(substr($Txt,0,$Pos - 1),'<');
			}
		}

		if ($Pos!==false) {

			// Check the name of the tag
			if (strcasecmp(substr($Txt,$Pos+1,mb_strlen($Tag)),$Tag)==0) {
				$PosX = $Pos + 1 + mb_strlen($Tag); // The next char
				$TagOk = true;
				$TagIsOpening = true;
			} elseif (strcasecmp(substr($Txt,$Pos+1,mb_strlen($TagClosing)),$TagClosing)==0) {
				$PosX = $Pos + 1 + mb_strlen($TagClosing); // The next char
				$TagOk = true;
				$TagIsOpening = false;
			}

			if ($TagOk) {
				// Check the next char
				$x = $Txt[$PosX];
				if (($x===' ') or ($x==="\r") or ($x==="\n") or ($x==='>')) {
					// Check the encapsulation count
					if ($LevelStop===false) { // No encaplusation check
						if ($TagIsOpening!==$Opening) $TagOk = false;
					} else { // Count the number of level
						if ($TagIsOpening) {
							$LevelNum++;
						} else {
							$LevelNum--;
						}
						// Check if it's the expected level
						if ($LevelNum!=$LevelStop) $TagOk = false;
					}
				} else {
					$TagOk = false;
				}
			} //--> if ($TagOk)

		}
	} while (($Pos!==false) and ($TagOk===false));

	// Search for the end of the tag
	if ($TagOk) {
		$Loc = new clsTbsLocator;
		if ($WithPrm) {
			$PosEnd = 0;
			clsTinyButStrong::f_Loc_PrmRead($Txt,$PosX,true,'\'"','<','>',$Loc,$PosEnd);
		} else {
			$PosEnd = strpos($Txt,'>',$PosX);
			if ($PosEnd===false) {
				$TagOk = false;
			}
		}
	}

	// Result
	if ($TagOk) {
		$Loc->PosBeg = $Pos;
		$Loc->PosEnd = $PosEnd;
		return $Loc;
	} else {
		return false;
	}

}