getElementByTagName和getAttribute在PHP中是否区分大小写?

3

我创建了一个简单的PHP脚本,使用getElementByTagName和getAttribute解析HTML文档并返回meta标签。它完美地工作,除了一个问题,如果HTML标签不是小写,则不返回标签内容。例如:

<title>My Title</title>

将返回"My Title",但

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

你不能在使用正则表达式之前将HTML转换为小写吗? - Enijar
@Enijar:那会改变整个内容,而不仅仅是标签。 - Amal Murali
为什么要使用除小写字母以外的标签呢?只使用小写字母(除了doctype等少数例外)是一种好的实践。 - putvande
$doc 的值从哪里来?如果构建 DOM 的任何内容没有(不区分大小写的)HTML 选项,我会感到惊讶。 - Quentin
@putvande 这个脚本用于扫描外部网站的标签。个人而言,我总是使用小写字母,但我的一个同事在使用该工具时遇到了一些区分大小写的网站,导致该工具无法正常工作。 - zen_mind
@Quentin,$doc的值来自脚本之前的部分,我没有发布整个脚本,因为它非常长。这是值的来源:$html = file_get_contents_curl("$url"); $doc = new DOMDocument(); @$doc->loadHTML($html); - zen_mind
3个回答

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"

0
一个 XML 文档可以拥有两个不同的元素,分别命名为 Title 和 title,意图是要使它们不同。将它们转换/处理成相同的名称是一个错误,可能会产生严重后果。
在您的情况下,您可以利用 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>

0

考虑到你正在使用的内容,答案是否定的。getElementsByTagName用于解析XML DOM,而XML允许区分大小写的标签名称。

你可以尝试每个Title、tItle、tiTle等的迭代,但这样会非常慢。通常你只会看到三个选项(全小写、首字母大写和全大写),这使得你的工作变得更容易。


3
XML不只是“允许”大小写敏感的标签名 - 它是必须这样。在XML中,标签名和属性名始终是大小写敏感的。 - BoltClock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接