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; } }
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; } }