使用PHP提取字符串的一些XML标记

时间:2014-10-05 14:42:45

标签: php xml simplexml

我有以下功能:

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

5 个答案:

答案 0 :(得分:3)

你的问题有两个部分。

  1. 将带有标签的片段加载到XML文档中
  2. 从XML中获取数据
  3. 将数据加载到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>
    

    正如您所看到的,它保留了语言名称元素,但将所有名称转换为小写。如果缺少htmlbody元素,它总会添加,但这不是问题。

    从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>
    

答案 1 :(得分:0)

这种方法可能会对您有所帮助。我不是用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>

答案 2 :(得分: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)

即可

答案 3 :(得分:0)

如前所述:在版本2中,您的XML无效,因为您在XML-Tags中使用了非结束HTML。

如果要将HTML保留在XML中,则需要通过HTML实体替换HTML代码的特殊字符。为此,您可以使用函数htmlspecialchars()。您也可以使用htmlentities()作为替代方案。后者替换了更多的字符。

可以使用函数html_entity_decode()来替换HTML实体。

示例:

$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-Tags中,而不会干扰XML-Syntax:

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

要从$data获取原始HTML,首先必须使用您的函数提取所选语言的值。然后使用html_entity_decode()解码转换后的HTML。

答案 4 :(得分: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>