Извлечь некоторые XML-теги строки с помощью переполнения стека

У меня есть следующая функция:

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

4

Решение

Твоя проблема состоит из двух частей.

  1. Загрузить фрагмент с тегами в документ XML
  2. Извлекать данные из XML

Загрузка данных в XML

Основная проблема здесь заключается в том, что это не допустимый фрагмент 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 элементы, если они отсутствуют, но это не проблема.

Получить данные из XML

Теперь, когда у вас есть 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>
3

Другие решения

Этот подход может помочь вам. Я не включаю данные в 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>
0

Я не уверен, что это может соответствовать вашим целям, но вы можете проверить свои теги с помощью регулярных выражений.

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)

0

Как уже упоминалось ранее: в версии 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 является:

&lt;li&gt;&lt;span class=&quot;pull-right&quot;&gt;25 GB&lt;/span&gt;Espace disque

То же самое должно быть сделано для английского значения, хранящегося в $htmlSpecialEnglish для этого примера.

Преобразованный HTML может быть включен в XML-теги без вмешательства в XML-синтаксис:

$data = "<French>$htmlSpecialFrench</French><English>$htmlSpecialEnglish</English>"

Чтобы получить ваш оригинальный HTML от $data сначала вы должны извлечь значение выбранного языка с помощью вашей функции. Тогда вы используете html_entity_decode() декодировать ваш преобразованный HTML.

0

Я не знаю, что вы имеете в виду, но, возможно, это поможет:

Скопируйте скрипт и вставьте в дизайнер вкладка и получить скрипт в код вкладка (используйте Dreamweaver, чтобы справиться с этим.
например:

<?php
$params= '<English>&lt;h1&gt;Hello&lt;/h1&gt;</English><French>&lt;h1&gt;Bonjour&lt;/h1&gt;</French>';
print $params;
?>

&lt;h1&gt; for <h1>
&lt;/h1&gt; for</h1>
0
По вопросам рекламы [email protected]