У меня есть следующая функция:
function translate($params) {
$xmldata = '<?xml version="1.0" encoding="UTF-8" ?><root>' . html_entity_decode($params['data']) . '</root>';
$lang = ucfirst(strtolower($params['lang']));
if (simplexml_load_string($xmldata) === FALSE) {
return $params['data'];
} else {
$langxmlobj = new SimpleXMLElement($xmldata);
if ($langxmlobj -> $lang) {
return ($langxmlobj -> $lang);
} else {
return $params['data'];
}
}
}
Который прекрасно работает с такими строками, как:
$params['data'] = '<English>Hello</English><French>Bonjour</French>';
$params['lang'] = 'English';
print translate($params);
это выводит:
Hello
Но …
Если в строке есть другие теги:
$params['data'] = '<English><h1>Hello</h1></English><French><h1>Bonjour</h1></French>';
$params['lang'] = 'English';
Ничего не выводит;
Я хотел, чтобы это вывело:
<h1>Hello</h1> or any other tag within the <LanguageQuotes>
Вытаскивая мои волосы здесь; любая идея ?
Version2:
Это не работает, когда строка похожа на:
$data = '<French><li><span class="pull-right">25 GB</span>Espace disque</French><English><li><span class="pull-right">25 GB</span>Disk Space</English>
<French><li><span class="pull-right">YES</span>PHP 5, MySQL 5</French><English><li><span class="pull-right">YES</span>PHP 5, MySQL 5</English>
<French><li><span class="pull-right">100</span>Bases de données</French><English><li><span class="pull-right">100</span>Databases</English>
<French><li><span class="pull-right">∞</span>E-Mails</French><English><li><span class="pull-right">∞</span>E-mails</English>';
Твоя проблема состоит из двух частей.
Основная проблема здесь заключается в том, что это не допустимый фрагмент XML, а смесь фрагментов HTML с некоторыми конкретными тегами. К счастью, DOMDocument может загружать (и восстанавливать) HTML. Это не будет загружать данные как UTF-8 по умолчанию, вам нужно добавить метатег, указывающий кодировку.
$data = '<French><li><span class="pull-right">25 GB</span>Espace disque</French><English><li><span class="pull-right">25 GB</span>Disk Space</English>
<French><li><span class="pull-right">YES</span>PHP 5, MySQL 5</French><English><li><span class="pull-right">YES</span>PHP 5, MySQL 5</English>
<French><li><span class="pull-right">100</span>Bases de données</French><English><li><span class="pull-right">100</span>Databases</English>
<French><li><span class="pull-right">∞</span>E-Mails</French><English><li><span class="pull-right">∞</span>E-mails</English>';
$html_data =
'<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>
<body>'.$data.'</body>';
libxml_use_internal_errors(TRUE);
$dom = new DOMDocument();
$dom->loadHtml($html_data);
$dom->formatOutput = TRUE;
echo $dom->saveXml();
Выход:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<body>
<french>
<li><span class="pull-right">25 GB</span>Espace disque</li>
</french>
<english>
<li><span class="pull-right">25 GB</span>Disk Space</li>
</english>
<french>
<li><span class="pull-right">YES</span>PHP 5, MySQL 5</li>
</french>
<english>
<li><span class="pull-right">YES</span>PHP 5, MySQL 5</li>
</english>
...
</body>
</html>
Как видите, он сохраняет элементы имени языка, но преобразует все имена в нижний регистр. Всегда добавляет html
а также body
элементы, если они отсутствуют, но это не проблема.
Теперь, когда у вас есть DOM, вы можете использовать XPath для извлечения узлов.
Одна из возможностей — получить элемент body и импортировать его в SimpleXML:
$xpath = new DOMXpath($dom);
$root = simplexml_import_dom($xpath->evaluate('/html/body')->item(0));
var_dump($root);
Выход:
object(SimpleXMLElement)#4 (2) {
["french"]=>
array(4) {
[0]=>
object(SimpleXMLElement)#3 (1) {
["li"]=>
object(SimpleXMLElement)#12 (1) {
["span"]=>
string(5) "25 GB"}
}
...
}
["english"]=>
array(4) {
[0]=>
object(SimpleXMLElement)#5 (1) {
["li"]=>
object(SimpleXMLElement)#12 (1) {
["span"]=>
string(5) "25 GB"}
}
...
Или извлеките узлы напрямую и сохраните их как фрагменты HTML:
$xpath = new DOMXpath($dom);
$string = '';
foreach ($xpath->evaluate('/html/body/*[name() = "english"]/*') as $node) {
$string .= $dom->saveHtml($node);
}
echo $string;
Выход:
<li>
<span class="pull-right">25 GB</span>Disk Space</li><li>
<span class="pull-right">YES</span>PHP 5, MySQL 5</li><li>
<span class="pull-right">100</span>Databases</li><li>
<span class="pull-right">∞</span>E-mails</li>
Этот подход может помочь вам. Я не включаю данные в XML, я не думаю, что это необходимо здесь. Вам просто нужно найти данные между двумя пользовательскими тегами.
/**
* $matches[0] -> Returns string with the custom tag
* $matches[1] -> Returns string without the custom tag
*
* @param string $data
* @param string $tag
* @return string
*/
function find_between_custom_tag($data, $tag) {
$regex = '/<' . $tag . '>(.*?)<\/' . $tag . '>/';
preg_match($regex, $data, $matches);
return $matches[1];
}
$data = '<English><h1>Hello</h1></English><French><h1>Bonjour</h1></French>';
$tag = 'English';
echo '<pre>';
echo htmlspecialchars( find_between_custom_tag($data, $tag) );
echo '</pre>';
Выходы:
<h1>Hello</h1>
Я не уверен, что это может соответствовать вашим целям, но вы можете проверить свои теги с помощью регулярных выражений.
function extractXML($data,$ce) {
$all = array(
"en" => "english",
"fr" => "french",
);
$lang = $all[$ce];
if (!$lang) { $lang='english'; }
$re = "/\<".$lang."?\>(.*?)\<\/".$lang."\>/i";
preg_match_all($re,$data,$matches);
foreach ($matches[1] as $name) {
$return .= $name;
}
return $return;
}
//Load your XML data
$test = '
<english>This is in english</english>
<english><div><span>This is also in english</span></div></english>
<french><div><span>This is some text</span></div></french>
<french><span>Regex Power!</span></french>
';
$str = '<?xml version="1.0" encoding="UTF-8" ?><root></root>';
echo $str.extractXMLLang($test,'en');
Это возвращает все теги из языков правильно. Просто используйте extractXMLLang(String,Language-Abbreviation)
Как уже упоминалось ранее: в версии 2 ваш XML недействителен, потому что вы используете незамкнутый HTML-код внутри своих XML-тегов.
Если вы хотите сохранить HTML в XML, вам нужно заменить специальные символы HTML-кода его HTML-сущностью. Для этого вы можете использовать функцию htmlspecialchars()
, Вы также можете использовать htmlentities()
как альтернатива. Последний заменяет больше символов.
Заменить HTML-сущности его символами можно с помощью функции html_entity_decode()
,
Пример:
$htmlSpecialFrench = htmlspecialchars('<li><span class="pull-right">25 GB</span>Espace disque');
Тогда значение $htmlSpecialFrench
является:
<li><span class="pull-right">25 GB</span>Espace disque
То же самое должно быть сделано для английского значения, хранящегося в $htmlSpecialEnglish
для этого примера.
Преобразованный HTML может быть включен в XML-теги без вмешательства в XML-синтаксис:
$data = "<French>$htmlSpecialFrench</French><English>$htmlSpecialEnglish</English>"
Чтобы получить ваш оригинальный HTML от $data
сначала вы должны извлечь значение выбранного языка с помощью вашей функции. Тогда вы используете html_entity_decode()
декодировать ваш преобразованный HTML.
Я не знаю, что вы имеете в виду, но, возможно, это поможет:
Скопируйте скрипт и вставьте в дизайнер вкладка и получить скрипт в код вкладка (используйте Dreamweaver, чтобы справиться с этим.
например:
<?php
$params= '<English><h1>Hello</h1></English><French><h1>Bonjour</h1></French>';
print $params;
?>
<h1> for <h1>
</h1> for</h1>