使用getElementByTagName和getAttribute进行区分大小写 - PHP

时间:2014-05-02 11:11:21

标签: php html xml regex

我创建了一个简单的PHP脚本,它解析HTML文档并使用getElementByTagName和getAttribute返回元标记。它完全不同于一件事,如果HTML标签不是小写,那么它不会返回标签的内容。例如:

<title>My Title</title>

将返回&#34;我的标题&#34;但是

<Title>My Title</Title>

<TITLE>My Title</TITLE> 

什么都不会返回。无论如何,有没有简单的方法让它匹配标签?我猜它可能涉及正则表达式。

以下代码示例:

$nodes = $doc->getElementsByTagName('title');
$heading = $doc->getElementsByTagName('h1');
$title = $nodes->item(0)->nodeValue;
$h1 = $heading->item(0)->nodeValue;

$metas = $doc->getElementsByTagName('meta');

for ($i = 0; $i < $metas->length; $i++)
{
$meta = $metas->item($i);
if($meta->getAttribute('name') == 'description')
    $description = $meta->getAttribute('content');
if($meta->getAttribute('name') == 'keywords')
    $keywords = $meta->getAttribute('content');
if($meta->getAttribute('name') == 'robots')
    $robots = $meta->getAttribute('content');
}

3 个答案:

答案 0 :(得分:2)

DOMDocument :: loadHtml()将所有元素转换为小写(并删除命名空间)。这是一个小型演示:

$html = <<<'HTML'
<html><Body><Title>My Title</Title></Body></html>
HTML;

$dom = new DOMDocument();
$dom->loadHtml($html);
echo $dom->saveHtml();

输出:https://eval.in/145538

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><title>My Title</title></body></html>

Xml区分大小写。因此,如果您将某些内容加载为XML,它将按照它们的方式保留元素:

$html = <<<'HTML'
<html><Body><Title>My Title</Title></Body></html>
HTML;

$dom = new DOMDocument();
$dom->loadXml($html);
echo $dom->saveXml();

输出:https://eval.in/145539

<?xml version="1.0"?>
<html><Body><Title>My Title</Title></Body></html>

这将影响DOM方法和Xpath:

$html = <<<'HTML'
<html><Body><Title>My Title</Title></Body></html>
HTML;

$dom = new DOMDocument();
$dom->loadHtml($html);

var_dump(
  // One element "title"
  $dom->getElementsByTagName('title')->length
);

$xpath = new DOMXpath($dom);
var_dump(
  // "title" as string
  $xpath->evaluate('string(//title)')
);

输出:https://eval.in/145541

int(1)
string(8) "My Title"

答案 1 :(得分:0)

答案是否定的,假设您使用的是什么。 getElementsByTagName用于解析XML DOM,XML允许区分大小写的标记名称。

你可以通过尝试Title,tItle,tiTle等的每次迭代来超慢速路线,但是你通常只会看到你提到的三个选项(全部 - 低,初始 - 上限和所有-caps),这使你的工作更容易。

答案 2 :(得分:0)

XML文档可以分别具有两个不同的元素:标题和标题 - 它们是不同的。将它们转换/处理为同名是一个可能产生严重后果的错误。

但是,在您的情况下,您可以使用XSLT将所有大写字符转换为小写字符,如this answer中所述。

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vUpper" select=
 "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:variable name="vLower" select=
 "'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="*[name()=local-name()]" priority="2">
  <xsl:element name="{translate(name(), $vUpper, $vLower)}"
   namespace="{namespace-uri()}">
       <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="*" priority="1">
  <xsl:element name=
   "{substring-before(name(), ':')}:{translate(local-name(), $vUpper, $vLower)}"
   namespace="{namespace-uri()}">
       <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="@*[name()=local-name()]" priority="2">
  <xsl:attribute name="{translate(name(), $vUpper, $vLower)}"
   namespace="{namespace-uri()}">
       <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="@*" priority="1">
  <xsl:attribute name=
   "{substring-before(name(), ':')}:{translate(local-name(), $vUpper, $vLower)}"
   namespace="{namespace-uri()}">
     <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>