首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >HTML DOM:如何在不丢失子元素的情况下获取元素?

HTML DOM:如何在不丢失子元素的情况下获取元素?
EN

Stack Overflow用户
提问于 2011-03-15 02:19:05
回答 3查看 915关注 0票数 1

我正在尝试对HTML中的文本执行preg_replace。我希望避免替换标记中的文本,因此我将字符串作为DOM元素加载,并获取每个节点中的文本。例如,我有这个列表:

代码语言:javascript
运行
复制
<ul>
<li><a href="?p=oconnorinv&i=1">Boxes 1-3</a>: 1925 - 1928 <em>(A-Ma)</em></li>
<li><a href="?p=oconnorinv&i=2">Boxes 4-6</a>: 1928 <em>(Mb-Z)</em> - 1930 <em>(A-Wi)</em></li>
<li><a href="?p=oconnorinv&i=3">Boxes 7-9</a>: 1930 <em>(Wo-Z)</em>- 1932 <em>(A-Fl)</em></li>
</ul>

我希望能够突出显示字符"1“或字母"i",而不干扰链接或列表项标记。所以我抓取每个列表项并获取它的值来执行替换:

代码语言:javascript
运行
复制
$invfile = [string of the unordered list above]
$invcontents = new DOMDocument;
$invcontents->loadHTML($invfile);
$inv_listitems = $invcontents->getElementsByTagName('li');
    foreach ($inv_listitems as $f) {
            $f->nodeValue = preg_replace($to_highlight, "<span class=\"highlight\">$0</span>", $f->nodeValue);
        }
    echo html_entity_decode($invcontents->saveHTML());

问题是,当我获取节点值时,列表项中的子节点会丢失。如果按原样打印原始字符串,、< em >等标记都在那里。但当我运行该脚本时,它打印出的内容没有链接或任何格式化标记。例如,如果我的$to_replace是字符串"Boxes",则列表变为:

代码语言:javascript
运行
复制
<ul>
<li><span class="highlight">Boxes</span> 1-3: 1925 - 1928 (A-Ma)</li>
<li><span class="highlight">Boxes</span> 4-6: 1928 (Mb-Z) - 1930 (A-Wi)</li>
<li><span class="highlight">Boxes</span> 7-9: 1930 (Wo-Z)- 1932 (A-Fl)</li>
</ul>

怎样才能在不丢失标签的情况下获得文本?

EN

回答 3

Stack Overflow用户

发布于 2011-03-15 02:41:04

这里的问题是,你是在整个

  • 元素。Boxes是锚标签的nodeValue的一部分。

如果上面的结构总是相同的,你可以这样做

$new_html = preg_replace("##","",$f->item(0)->nodeValue);

实际上,最好的方法是取消设置锚点的节点值,创建一个全新的元素并追加它。

(考虑下面的psuedo代码)

$inv_listitems = $invcontents->getElementsByTagName('li');foreach ($inv_listitems as $f) { $span = $invcontents->createElement("span");$span->setAttribute("class","highlight");$span->nodeValue = $f->item(0)->nodeValue;$f->appendChild($span);} echo $invcontents>saveHTML();

你必须在那里做一些匹配,以及取消设置$f的nodeValue,但希望这能让它更清楚一些。

另外,不要在nodeValue中直接设置HTML,因为它会对您设置的所有html运行htmlentities()。这就是我在上面创建一个新元素的原因。如果一定要在nodeValue中设置超文本标记语言,那么应该创建一个DocumentFragment Object

票数 0
EN

Stack Overflow用户

发布于 2011-03-15 03:32:04

你最好只在文本节点上操作:

代码语言:javascript
运行
复制
$x  = new DOMXPath(invcontents);
foreach($x->query('//li/text()' as $textnode){
    //replace text node with list of plain text nodes & your highlighting span.
}
票数 0
EN

Stack Overflow用户

发布于 2013-02-22 14:03:46

对于这类操作,我总是使用xpath。它会给你更多的灵活性。此示例处理

代码语言:javascript
运行
复制
<mainlevel>
  <toplevel>
    <detaillevel key=...>
      <xmlvalue1></xmlvalue1>
      <xmlvalue1></xmlvalue2>

      <sublevel key=...>
        <xmlvalue1></xmlsubvalue1>
        <xmlvalue1></xmlsubvalue2>
      </sublevel>

    </detaillevel>
  </toplevel>
</mainlevel>

要解析它,请执行以下操作:

代码语言:javascript
运行
复制
$xpath = new DOMXPath($xmlDoc);
$mainNodes = $xpath->query("/mainlevel/toplevel/detaillevel");

foreach( $mainNodes as $subNode ) { 
    $parameter1=$subNode->getAttribute('key');
    $parameter2=$subNode->getElementsByTagName("xmlvalue1")->item(0)->nodeValue;
    $parameter3=$subNode->getElementsByTagName("xmlvalue2")->item(0)->nodeValue;

    foreach ($subNode->getElementsByTagName("sublevel") as $detailNode) {
        $parameter1=$detailNode->getAttribute('key');
        $parameter2=$detailNode->getAttribute('xmlsubvalue1');
        $parameter2=$detailNode->getAttribute('xmlsubvalue2');

        }
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5302653

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档