function showPhpCode() { $oNodeAdded = $this->oDiffAdded->getNode(); $this->oDiffAdded->setNode(AnwXml::xmlShowPhpCode($oNodeAdded)); $oNodeDeleted = $this->oDiffDeleted->getNode(); $this->oDiffDeleted->setNode(AnwXml::xmlShowPhpCode($oNodeDeleted)); }
private function exportData($aaExportPageGroups) { $oDoc = new DOMDocument("1.0", "UTF-8"); //put information as comment $sComment = ""; $sComment .= $this->t_("xmlcomment_info") . "\n"; $sComment .= ANWIKI_WEBSITE . "\n\n"; $sComment .= $this->t_("xmlcomment_time", array("time" => Anwi18n::dateTime(time()))) . "\n"; $sComment .= $this->t_("xmlcomment_version", array("version" => ANWIKI_VERSION_NAME)) . "\n"; $sComment .= $this->t_("xmlcomment_user", array("user" => AnwCurrentSession::getUser()->getLogin())) . "\n"; $sComment .= $this->t_("xmlcomment_from", array("url" => self::globalCfgUrlRoot())) . "\n\n"; $sComment .= $this->t_("xmlcomment_contents") . "\n"; //list exported contents as comment foreach ($aaExportPageGroups as $amPageGroup) { foreach ($amPageGroup['PAGES'] as $oPage) { $sPageTime = Anwi18n::dateTime($oPage->getTime()); $sComment .= ' * ' . $oPage->getName() . " (" . $oPage->getLang() . ") (" . $sPageTime . ")\n"; } } $sCommentSeparator = "\n**************************************************\n"; $sComment = " " . $sCommentSeparator . $sComment . $sCommentSeparator . " "; $oCommentNode = $oDoc->createComment($sComment); $oDoc->appendChild($oCommentNode); //end comment //<anwexport time="" origin=""> $oRootNode = $oDoc->createElement(self::XMLTAG_ROOT); $oRootNode->setAttribute("time", time()); $oRootNode->setAttribute("from", AnwXml::xmlFileAttributeEncode(self::globalCfgUrlRoot())); $oRootNode->setAttribute("version_id", ANWIKI_VERSION_ID); $oRootNode->setAttribute("version_name", AnwXml::xmlFileAttributeEncode(ANWIKI_VERSION_NAME)); $oDoc->appendChild($oRootNode); foreach ($aaExportPageGroups as $amPageGroup) { $oPageGroup = $amPageGroup['GROUP']; $sContentClassName = $oPageGroup->getContentClass()->getName(); //<anwpagegroup> $oPageGroupNode = $oDoc->createElement(self::XMLTAG_PAGEGROUP); $oPageGroupNode->setAttribute("contentclass", AnwXml::xmlFileAttributeEncode($sContentClassName)); foreach ($amPageGroup['PAGES'] as $oPage) { //add comment $sPageTime = Anwi18n::dateTime($oPage->getTime()); $sComment = $oPage->getName() . " (" . $oPage->getLang() . ") (" . $sPageTime . ") (" . $oPageGroup->getContentClass()->getLabel() . "/" . $sContentClassName . ")"; //$sComment = " \n*\n* ".$sComment."\n*\n "; $sCommentSeparator = "\n**************************************************\n"; $sComment = " \n\n" . $sCommentSeparator . $sComment . $sCommentSeparator . " "; $oCommentNode = $oDoc->createComment($sComment); $oPageGroupNode->appendChild($oCommentNode); //end comment //using a CDATA node to preserve source breaklines :-) //$sPageContent = $oPage->getContent()->toXml(); //$oPageContentNode = $oDoc->createCDATASection($sPageContent); $oContentNodeDoc = $oPage->getContent()->toXml()->documentElement; //here we got a <doc> node $oPageContentNodeDoc = $oDoc->importNode($oContentNodeDoc, true); //<anwpage name="" lang="" time=""> $oPageNode = $oDoc->createElement(self::XMLTAG_PAGE); $oPageNode->setAttribute("name", AnwXml::xmlFileAttributeEncode($oPage->getName())); $oPageNode->setAttribute("lang", AnwXml::xmlFileAttributeEncode($oPage->getLang())); $oPageNode->setAttribute("time", $oPage->getTime()); //we need to do this to squeeze the unwanted <doc> node in //WARNING - special loop ! childs are getting modified... while ($oChildNode = $oPageContentNodeDoc->childNodes->item(0)) { $oPageNode->appendChild($oChildNode); } $oPageGroupNode->appendChild($oPageNode); } $oRootNode->appendChild($oPageGroupNode); } $sReturn = AnwUtils::xmlDumpNode($oRootNode); // even if final XML structure may be broken due to undeclared namespaces used in content, // we let raw content as it is for better compatibility in later versions. // $sReturn = AnwXml::prepareXmlValueToXml($sReturn); return $sReturn; }
private function findSubDeletedDiffs() { $oNode = $this->oNode; if (AnwXml::xmlIsTextNode($oNode) || AnwXml::xmlIsPhpNode($oNode) || AnwXml::xmlIsCommentNode($oNode)) { return; } $oChilds = $oNode->childNodes; if ($oChilds) { $this->aoSubDeletedDiffs = array(); for ($i = 0; $i < $oChilds->length; $i++) { $oChild = $oChilds->item($i); $oSubDiff = new AnwDiffDeleted($oChild, $this); $this->aoSubDeletedDiffs[] = $oSubDiff; } } }
function showPhpCode() { if ($this->oMovedNode) { $this->oMovedNode = AnwXml::xmlShowPhpCode($this->oMovedNode); } }
private function getDataFromXmlFile($sFilename) { //load XML from file if (!file_exists($sFilename)) { throw new AnwBadCallException("import file not found"); } $sFileContent = AnwUtils::file_get_contents($sFilename); $oRootNode = AnwUtils::loadXml($sFileContent); $aaData = array(); $aaData['PAGEGROUPS'] = array(); $aaData['TIME'] = $oRootNode->getAttribute("time"); $aaData['FROM'] = AnwXml::xmlFileAttributeDecode($oRootNode->getAttribute("from")); $aaData['VERSION_ID'] = $oRootNode->getAttribute("version_id"); $aaData['VERSION_NAME'] = AnwXml::xmlFileAttributeDecode($oRootNode->getAttribute("version_name")); $aoPageGroupsNodes = AnwXml::xmlGetChildsByTagName(self::XMLTAG_PAGEGROUP, $oRootNode); foreach ($aoPageGroupsNodes as $oPageGroupNode) { $aaDataGroup = array(); $aaDataGroup['CONTENTCLASS'] = AnwXml::xmlFileAttributeDecode($oPageGroupNode->getAttribute("contentclass")); $aaDataGroup['PAGES'] = array(); $aoTranslationsNodes = AnwXml::xmlGetChildsByTagName(self::XMLTAG_PAGE, $oPageGroupNode); foreach ($aoTranslationsNodes as $oPageNode) { $asDataPage = array(); $asDataPage['NAME'] = AnwXml::xmlFileAttributeDecode($oPageNode->getAttribute("name")); $asDataPage['LANG'] = AnwXml::xmlFileAttributeDecode($oPageNode->getAttribute("lang")); $asDataPage['TIME'] = (int) $oPageNode->getAttribute("time"); $asDataPage['CONTENT'] = AnwUtils::xmlDumpNodeChilds($oPageNode); $aaDataGroup['PAGES'][] = $asDataPage; } $aaData['PAGEGROUPS'][] = $aaDataGroup; } return $aaData; }
function getTranslatedPercent_onTextValue($oRootNode, $sInputName) { $this->tmp_nTranslatedValuesTotal++; if (!AnwXml::xmlIsUntranslated($oRootNode)) { $this->tmp_nTranslatedValuesTranslated++; } }
private static function findMovedNodes_findDeleted($aoDiffs, $oDiffAdded) { $oNodeRef = $oDiffAdded->getNode(); foreach ($aoDiffs as $i => $oDiff) { if ($oDiff->getDiffType() == AnwDiff::TYPE_DIFFS) { $oDiffDeleted = self::findMovedNodes_findDeleted($oDiff->getAllDiffs(), $oDiffAdded); if ($oDiffDeleted) { return $oDiffDeleted; } } else { if ($oDiff->getDiffType() == AnwDiff::TYPE_DELETED && !$oDiff->getMovedDiff() || $oDiff->getDiffType() == AnwDiff::TYPE_EDITED && !$oDiff->getDiffDeleted()->getMovedDiff()) { if ($oDiff->getDiffType() == AnwDiff::TYPE_EDITED) { $oDiff = $oDiff->getDiffDeleted(); //... //AnwDebug::logdetail("findMovedNodes : !special EDITED !!!"); } //AnwDebug::log("findMovedNodes : compare ".htmlentities(AnwUtils::xmlDumpNode($oNodeRef))." <---> ".htmlentities(AnwUtils::xmlDumpNode($oDiff->getNode()))); //warning: do the test hasSubMovedDiff() here, not before, as there could be a valid subdeleted node child of a parent deletednode having already another subdeletednode if (!$oDiff->getMovedDiff() && !$oDiff->hasSubMovedDiff() && AnwXml::xmlAreSimilarNodesAllowTextLayoutChange($oDiff->getNode(), $oNodeRef)) { return $oDiff; } else { if ($oDiff->hasSubDeletedDiffs()) { //continue search into subdeleted diffs $aoSubDiffs = $oDiff->getSubDeletedDiffs(); $oDiffDeleted = self::findMovedNodes_findDeleted($aoSubDiffs, $oDiffAdded); if ($oDiffDeleted) { return $oDiffDeleted; } } } } } } return false; }
static function pubcallOperator($sArg, $sValue, $sLang, $asOperatorArgs = array()) { switch ($sArg) { case "firstwords": $sReturn = AnwXml::xmlGetUntranslatedTxt($sValue, false); $nFirstWordsLength = self::FIRSTWORDS_LENGTH; if (isset($asOperatorArgs[0]) && intval($asOperatorArgs[0]) > 0) { $nFirstWordsLength = intval($asOperatorArgs[0]); } if (strlen($sReturn) > self::FIRSTWORDS_LENGTH) { $sReturn = AnwUtils::firstWords($sValue, $nFirstWordsLength) . '...'; } return $sReturn; break; case "date": $sReturn = Anwi18n::date($sValue, $sLang); return $sReturn; break; case "datetime": $sReturn = Anwi18n::dateTime($sValue, $sLang); return $sReturn; break; case "year": $sReturn = AnwUtils::date("Y", $sValue); return $sReturn; break; case "monthyear": $sReturn = AnwUtils::date("M Y", $sValue); return $sReturn; break; case "count": $sReturn = count($sValue); return $sReturn; break; case "len": $sReturn = strlen(trim($sValue)); return $sReturn; break; case "skipuntr": $sReturn = AnwUtils::renderUntr($sValue); return $sReturn; break; // numeric maths // numeric maths case "add": case "sub": case "mul": case "div": case "pow": if (isset($asOperatorArgs[0])) { $nNumber = intval($asOperatorArgs[0]); } switch ($sArg) { case "add": $sReturn = intval($sValue) + $nNumber; break; case "sub": $sReturn = intval($sValue) - $nNumber; break; case "mul": $sReturn = intval($sValue) * $nNumber; break; case "div": $sReturn = intval($sValue) / $nNumber; break; case "pow": $sReturn = intval($sValue) ^ $nNumber; break; } return $sReturn; break; default: $sReturn = AnwPlugins::vhook('contentclass_pubcalloperator_default', $sValue, $sArg); return $sReturn; break; } }
function showPhpCode() { $this->oNode = AnwXml::xmlShowPhpCode($this->oNode); }
static function xmlReplaceTextNode($oNode, $oNodeForReplace) { //ensure it's a text node if (!self::xmlIsTextNode($oNode)) { throw new AnwUnexpectedException("ReplaceTextNode on non text node"); } $oNode = AnwXml::xmlReplaceTextNodeValue($oNode, $oNodeForReplace->nodeValue); return $oNode; }
private static function doCheckSimilarContent($oContent1, $oContent2, $bTestAttributesValues = true) { if (!$oContent1) { throw new AnwUnexpectedException("checkSimilarContent : oContent1 is null"); } if (!$oContent2) { throw new AnwUnexpectedException("checkSimilarContent : oContent2 is null"); } if (!AnwXml::xmlSimilarStructure($oContent1->toXml(), $oContent2->toXml(), $bTestAttributesValues, true)) { /*print '<hr/>'; print 'Content1:'.htmlentities($oContent1->toXmlString()); print '<br/>***<br/>'; print 'Content2:'.htmlentities($oContent2->toXmlString());*/ throw new AnwUnexpectedException("Content desynchronization detected on checkSimilarContent"); } }
function testValue($sValue) { if (!AnwXml::xmlIsValid($sValue)) { //XML error found $sXmlErrors = '<ul>'; $aoLibXmlErrors = libxml_get_errors(); foreach ($aoLibXmlErrors as $oLibXmlError) { $sMessage = $oLibXmlError->message; if (!strstr($sMessage, "Premature end of data")) { //TODO dirty #CONTENTFIELDINPUTID# $sMessage = preg_replace('! line ([0-9]*) and doc!si', ' <a class="textareafocusline" onclick="setTextareaFocusLine($1,$(\'#CONTENTFIELDINPUTID#\'))">line $1</a>', $sMessage); $sXmlErrors .= '<li>' . $sMessage . '</li>'; } } $sXmlErrors .= '</ul>'; $sError = AnwComponent::g_editcontent("err_contentfield_xml_invalid", array("xmlerrors" => $sXmlErrors)); throw new AnwInvalidContentFieldValueException($sError); } else { if (AnwUtils::contentHasPhpCode($sValue)) { if ($this->bCheckPhpSyntax) { $sPhpError = null; //gets modified by evalMixedPhpSyntax if (AnwUtils::evalMixedPhpSyntax($sValue, $sPhpError)) { //print "ok"; } else { //better php error : hide file, and add a link to the line //TODO dirty #CONTENTFIELDINPUTID# $sPhpError = preg_replace('!in (.*) on line <b>([0-9]*)</b>!si', '<a class="textareafocusline" onclick="setTextareaFocusLine($2,$(\'#CONTENTFIELDINPUTID#\'))">on line $2</a>', $sPhpError); $sError = $sPhpError; throw new AnwInvalidContentFieldValueException($sError); } } } } }
private static function applyDiffsToTranslation($oRootNode, $oDiffs, $oContentField) { //AnwDebug::log("Applying diffs to : ".htmlentities(AnwUtils::xmlDumpNode($oRootNode))); $aoDiffs = $oDiffs->getAllDiffs(); $oChildNodes = $oRootNode->childNodes; $i = 0; foreach ($aoDiffs as $oDiff) { $oChild = $oChildNodes->item($i); if (!$oChild) { //AnwDebug::logdetail("oChild=null"); } AnwDebug::logdetail("//step dump: " . htmlentities(AnwUtils::xmlDumpNode($oRootNode))); $sDiffType = $oDiff->getDiffType(); $bSkipIncrement = false; switch ($sDiffType) { case AnwDiff::TYPE_ADDED: if ($oDiff->hasSubMovedNode()) { $oNodeRef = $oDiff->getNode(); $oNewNode = $oRootNode->ownerDocument->createElement($oNodeRef->nodeName); //no need to check for UnmodifiableBlockNodes, a comment/php node can't have submoved nodes AnwXml::xmlCopyNodeAttributes($oNodeRef, $oNewNode); //recursive call for SubAdded nodes AnwDebug::log(" * SUBADDED : " . htmlentities(AnwUtils::xmlDumpNode($oNewNode))); if ($oChild) { AnwDebug::logdetail("added->insertBefore : before=" . htmlentities(AnwUtils::xmlDumpNode($oChild))); $oRootNode->insertBefore($oNewNode, $oChild); } else { AnwDebug::logdetail("added->appendChild"); $oRootNode->appendChild($oNewNode); } //continue on subadded diffs self::applyDiffsToTranslation($oNewNode, $oDiff, $oContentField); } else { //quick test for special case with xmlIsUnmodifiableBlockNode $oTmpNode = $oDiff->getMovedNode() ? $this->getMovedNode() : $oDiff->getNode(); if (AnwXml::xmlIsUnmodifiableBlockNode($oTmpNode)) { //keep it unchanged $oNodeToImport = $oTmpNode; } else { //mark it as untranslated only if translatable (contentfield check) $bMarkAsUntranslated = AnwXml::xmlAreTranslatableAncestors($oRootNode, $oContentField); //TODO: move code from getNodeWithTranslateTags() here $oNodeToImport = $oDiff->getNodeWithTranslateTags($bMarkAsUntranslated, $oContentField); } $oNewNode = $oRootNode->ownerDocument->importNode($oNodeToImport, true); AnwDebug::log(" * ADDED : " . htmlentities(AnwUtils::xmlDumpNode($oNewNode))); if ($oChild) { AnwDebug::logdetail("added->insertBefore : before=" . htmlentities(AnwUtils::xmlDumpNode($oChild))); $oRootNode->insertBefore($oNewNode, $oChild); } else { AnwDebug::logdetail("added->appendChild"); $oRootNode->appendChild($oNewNode); } } break; case AnwDiff::TYPE_MOVED: //No need to import node as we get a node from the same document $oMovedNode = $oDiff->getMovedNode(); //tmp check if (!$oMovedNode) { //print AnwDebug::log('-----'.AnwUtils::xmlDumpNode($oDiff->getDiffDeleted()->getNode())); AnwDebug::log("****ERROR**** getMovedNode() returned NULL on AnwDiffMoved !"); throw new AnwUnexpectedException("ERROR getMovedNode() returned NULL on AnwDiffMoved !"); break; } AnwDebug::log(" * MOVED : " . htmlentities(AnwUtils::xmlDumpNode($oMovedNode))); //did the textlayout change? if ($oDiff->hasTextLayoutChanged()) { //we need to apply the new textlayout... $oMovedNode->nodeValue = AnwXml::xmlPreserveTextLayout($oMovedNode->nodeValue, $oDiff->getTextLayoutReferenceValue()); } //the following operations will MOVE the node into the document if ($oChild) { AnwDebug::log("added->insertBefore" . htmlentities(AnwUtils::xmlDumpNode($oMovedNode))); $oRootNode->insertBefore($oMovedNode, $oChild); } else { AnwDebug::logdetail("added->appendChild"); if (!$oRootNode->appendChild($oMovedNode)) { throw new AnwUnexpectedException("appendChild failed"); } } break; case AnwDiff::TYPE_DELETED: //if (!$oDiff->getMovedDiff()) //{ AnwDebug::logdetail(" * DELETED : " . htmlentities(AnwUtils::xmlDumpNode($oDiff->getNode())) . " == " . htmlentities(AnwUtils::xmlDumpNode($oChild))); //if (!$oRootNode->removeChild($oChild)) throw new AnwUnexpectedException("removeChild failed"); //$bSkipIncrement = true; // !!! We don't delete nodes now, because we may need it if it contains moved nodes... // these nodes will be deleted later ////self::$aoNodesMarkedForDeletion[] = array($oRootNode,$oChild); if (!$oRootNode->removeChild($oChild)) { throw new AnwUnexpectedException("removeChild failed"); } $bSkipIncrement = true; //} //else //{ // AnwDebug::log(" * DELETED : deletion skipped (node will be moved)"); //} break; case AnwDiff::TYPE_KEPT: //don't touch anything AnwDebug::log(" * KEPT : " . htmlentities(AnwUtils::xmlDumpNode($oDiff->getNode())) . " == " . htmlentities(AnwUtils::xmlDumpNode($oChild))); break; case AnwDiff::TYPE_EDITED: AnwDebug::log(" * EDITED : " . htmlentities(AnwUtils::xmlDumpNode($oChild)) . " == " . htmlentities(AnwUtils::xmlDumpNode($oDiff->getDiffAdded()->getNode()))); //TODO: warning, this code is very crappy and needs to be cleaned and tested //update attributes $oNodeRef = $oDiff->getDiffAdded()->getNode(); if (AnwXml::xmlIsUnmodifiableBlockNode($oChild)) { $oNewNode = AnwXml::xmlReplaceUnmodifiableBlockNode($oChild, $oNodeRef); } else { if (!AnwXml::xmlIsTextNode($oChild)) { throw new AnwUnexpectedException("not a text node in TYPE_EDITED"); } if ($oDiff->isEmpty() || !AnwXml::xmlAreTranslatableAncestors($oRootNode, $oContentField)) { AnwDebug::log("//edited : empty/untranslatable content, copying value but keeping it as translated"); //copy new value, but keep it as translated $oNewNode = AnwXml::xmlReplaceTextNode($oChild, $oNodeRef); } else { if ($oDiff->getDiffDeleted()->getMovedDiff()) { //special - consider it as an added node : set new value & mark this as untranslated AnwDebug::log("//edited : special case, considering as added node"); $oNewNode = AnwXml::xmlReplaceTextNode($oChild, $oNodeRef); $oNewNode = AnwXml::xmlSetTextUntranslated($oNewNode, true); } else { //content has really changed, mark it as untranslated if translatable (contentfield check) //current node is translatable... set new value & mark this as untranslated if ($oChild->nodeValue != $oNodeRef->nodeValue) { //we need to check if text has really changed, or if it's just some layout (spaces, breaklines...) which changed the nodeValue... $oNodeRefOld = $oDiff->getDiffDeleted()->getNode(); if (AnwXml::xmlTrimTextLayout($oNodeRefOld->nodeValue) == AnwXml::xmlTrimTextLayout($oNodeRef->nodeValue)) { AnwDebug::log("//edited : case 3.1, only textLayout has changed"); $sOldValue = $oChild->nodeValue; //content has not really changed, we just added/removed a space, tab, line break before/after the text value //ex: "blah blah\n" --> "blah blah\n\n" //we silently apply the new text layout, without turning it untranslated $oChild->nodeValue = AnwXml::xmlPreserveTextLayout($oChild->nodeValue, $oNodeRef->nodeValue); } else { AnwDebug::log("//edited : case 3.2, content has really changed"); $oNewNode = AnwXml::xmlReplaceTextNode($oChild, $oNodeRef); $oNewNode = AnwXml::xmlSetTextUntranslated($oNewNode, true); } } /* //current node is translatable... keep CURRENT value and mark it as untranslated $oNewNode = $oChild; if ($oNewNode->nodeValue != $oNodeRef->nodeValue) { $oNewNode = AnwXml::xmlSetTextUntranslated($oNewNode, true); }*/ } } } break; case AnwDiff::TYPE_DIFFS: $oNodeDiffRef = $oDiff->getNodeRootNew(); AnwDebug::log(" * DIFFS : " . htmlspecialchars(AnwUtils::xmlDumpNode($oNodeDiffRef)) . " == " . htmlentities(AnwUtils::xmlDumpNode($oChild))); //update attributes AnwXml::xmlCopyNodeAttributes($oNodeDiffRef, $oChild); //recursive call self::applyDiffsToTranslation($oChild, $oDiff, $oContentField); break; default: AnwDebug::log("ERROR - Unknown DiffType :" . $sDiffType); } //just to prevent erros... unset($oNewNode); unset($oNodeRef); if (!$bSkipIncrement) { //AnwDebug::logdetail(" * Loop i++"); $i++; //AnwDebug::logdetail("//step dump_end : ".htmlentities(AnwUtils::xmlDumpNode($oRootNode))); } //AnwDebug::log("Loop[$i] applydiffs intermediate result : ".htmlentities(AnwUtils::xmlDumpNode($oRootNode))); } //AnwDebug::log("applydiffs result : ".htmlentities(AnwUtils::xmlDumpNode($oRootNode))); return $oRootNode; }
function saveTranslation_onTextValue($oRootNode, $sFieldInput) { //escape < and > $sTranslatedValue = $this->getTranslatedValueFromPost($sFieldInput); $bTranslated = (int) AnwEnv::_POST("done-" . $sFieldInput) == 1 ? true : false; //deny empty values to avoid unsync if (trim($sTranslatedValue) == "") { $sTranslatedValue = self::EMPTY_VALUE; } AnwDebug::log(" --> {$sFieldInput} : " . ($bTranslated ? "TRANSLATED" : "UNTRANSLATED") . " : " . $sTranslatedValue . " ( was " . $oRootNode->nodeValue . ")"); //$oRootNode->nodeValue = $sTranslatedValue; $oRootNode = AnwXml::xmlReplaceTextNodeValue($oRootNode, $sTranslatedValue); $oRootNode = AnwXml::xmlSetTextUntranslated($oRootNode, !$bTranslated); //xml structure is now modified }
static function loadXML($sContent) { //TODO prepareXmlValueToXml should only be applied between <anwv/> tags $sContent = AnwXml::prepareXmlValueToXml($sContent); //we don't want > and < to be converted in normal chars but keep html entities as they are $sContent = str_replace('&', '&', $sContent); $oDoc = self::newDomDocument(); libxml_use_internal_errors(true); $bTest = $oDoc->loadXML($sContent); if (!$bTest) { throw new AnwUnexpectedException("loadXML failed"); } return $oDoc->documentElement; }