如何使用 DOM API 有条件地将元素包装在一起?

安德烈亚斯·米里奥尼斯

假设我们有这个输入:

<div wrap>1</div>
<div>2</div>
<div wrap>3</div>
<div wrap>4</div>
<div wrap>5</div>

所需的输出应该是:

<div class="wrapper">
  <div wrap>1</div>
</div>
<div>2</div>
<div class="wrapper">
  <div wrap>3</div>
  <div wrap>4</div>
  <div wrap>5</div>
</div>

此外,假设这些元素是 body 元素的直接子元素,并且在它们之前或之后可以有其他不相关的元素或文本节点。

请注意如何将连续元素分组在单个包装器中而不是单独包装。

您将如何处理 body 的 DOMNodeList 并将包装器插入到正确的位置?

在关于仅包装 body 元素的直接子元素的对话(评论)之后,

对于此输入:

<body>
  <div wrap>1
    <div wrap>1.1</div>
  </div>
  <div>2</div>
  <div wrap>3</div>
  <div wrap>4</div>
  <div wrap>5</div>
</body>

所需的输出应该是:

<body>
  <div class="wrapper">
    <div wrap>1
      <div wrap>1.1</div>
      <!–– ignored ––>.
    </div>
  </div>
  <div>2</div>
  <div class="wrapper">
    <div wrap>3</div>
    <div wrap>4</div>
    <div wrap>5</div>
  </div>
</body>

注意不是body 元素的直接后代的元素是如何被完全忽略的。

Nigel Ren

写起来很有趣,看到其他解决方案会很好,但无论如何这是我的尝试。

我在代码中添加了注释,而不是在这里描述方法,因为我认为注释更容易理解......

// Test HTML
$startHTML = '<div wrap>1</div>
<div>2</div>
<div wrap>3</div>
<div wrap>4</div>
<div wrap>5</div>';

$doc = new DOMDocument();
$doc->loadHTML($startHTML);

$xp = new DOMXPath($doc);
// Find any div tag with a wrap attribute which doesn't have an immediately preceeding
// tag with a wrap attribute, (or the first node which means it won't have a preceeding
// element anyway)
$wrapList = $xp->query("//div[@wrap='' and preceding-sibling::*[1][not(@wrap)]
                           or position() = 1]");

// Iterate over each of the first in the list of wrapped nodes
foreach ( $wrapList as $wrap )  {
    // Create new wrapper 
    $wrapper = $doc->createElement("div");
    $class = $doc->createAttribute("class");
    $class->value = "wrapper";
    $wrapper->appendChild($class);

    // Copy subsequent wrap nodes (if any)
    $nextNode = $wrap->nextSibling;
    while ( $nextNode ) {
        $next = $nextNode;
        $nextNode = $nextNode->nextSibling;
        // If it's an element (and not a text node etc)
        if ( $next->nodeType == XML_ELEMENT_NODE ) {
            // If it also has a wrap attribute - copy it
            if ($next->hasAttribute("wrap") ) {
                $wrapper->appendChild($next);
            }
            // If no attribute, then finished copying
            else    {
                break;
            }
        }
    }
    // Replace first wrap node with new wrapper
    $wrap->parentNode->replaceChild($wrapper, $wrap);
    // Move the wrap node into the wrapper
    $wrapper->insertBefore($wrap, $wrapper->firstChild);
}
echo $doc->saveHTML();

由于它使用 HTML,最终结果也全部包含在标准标签中,但输出(格式化)是......

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
    <body>
        <div class="wrapper">
            <div wrap>1</div>
        </div>
        <div>2</div>
        <div class="wrapper">
            <div wrap>3</div>
            <div wrap>4</div>
            <div wrap>5</div>
        </div>

    </body>
</html>

编辑:

如果您只想将其应用于<body>标记的直接后代,则更新 XPath 表达式以将其包含为条件的一部分...

$wrapList = $xp->query("//body/div[@wrap='' and preceding-sibling::*[1][not(@wrap)]
                       or position() = 1]");

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何有条件地将具有多个值的两行合并在一起并在R中进行突变?

来自分类Dev

AngularJS模板:如何有条件地将标签包装在另一个标签中

来自分类Dev

AngularJS模板:如何有条件地将标签包装在另一个标签中

来自分类Dev

使用jQuery将元素内容的子字符串包装在一起

来自分类Dev

如何有条件地与torch.cuda.device()一起使用

来自分类Dev

如何有条件地渲染来自API的响应

来自分类Dev

如何使用dom元素

来自分类Dev

一堂课后如何将所有兄弟姐妹包装在一起?(jQuery的)

来自分类Dev

根据范围属性有条件地将指令与另一个指令包装在一起

来自分类Dev

如何使用XSLT有条件地将多个XML元素转换为一个元素?

来自分类Dev

如何将两个jquery对象包装在一起?

来自分类Dev

使用PKCS#11将私钥和公钥包装在一起

来自分类Dev

使用Swig将C ++ for Python的多个类包装在一起

来自分类Dev

如何最好地将针对多个微服务的搜索服务与API网关集成在一起

来自分类Dev

如何遍历元素中的每个单词,然后有条件地包装匹配项?

来自分类Dev

sqlite3如何有条件地更改联接表中的字段(使用CASE..END和JOIN一起使用)?

来自分类常见问题

如何有条件地包装React组件?

来自分类Dev

Razor语法-如何有条件地包装一些内部HTML

来自分类Dev

使用Python API有条件地更新ElasticSearch文档

来自分类Dev

使用React-Query挂钩有条件地调用API

来自分类Dev

如何使swipejs与响应DOM一起使用?

来自分类Dev

有条件地将字符串粘贴在一起

来自分类Dev

Python; 有条件地将两个列表放在一起

来自分类Dev

如何将条件Required Attribute放入类属性以与WEB API一起使用?

来自分类Dev

在DOM准备就绪之前有条件地加载HTML元素

来自分类Dev

MustacheJS有条件地显示DOM

来自分类Dev

如何有条件地将元素插入列表?

来自分类Dev

如何有条件地将元素添加到 std::array - C++11

来自分类Dev

将jQuery与Shadow dom一起使用

Related 相关文章

  1. 1

    如何有条件地将具有多个值的两行合并在一起并在R中进行突变?

  2. 2

    AngularJS模板:如何有条件地将标签包装在另一个标签中

  3. 3

    AngularJS模板:如何有条件地将标签包装在另一个标签中

  4. 4

    使用jQuery将元素内容的子字符串包装在一起

  5. 5

    如何有条件地与torch.cuda.device()一起使用

  6. 6

    如何有条件地渲染来自API的响应

  7. 7

    如何使用dom元素

  8. 8

    一堂课后如何将所有兄弟姐妹包装在一起?(jQuery的)

  9. 9

    根据范围属性有条件地将指令与另一个指令包装在一起

  10. 10

    如何使用XSLT有条件地将多个XML元素转换为一个元素?

  11. 11

    如何将两个jquery对象包装在一起?

  12. 12

    使用PKCS#11将私钥和公钥包装在一起

  13. 13

    使用Swig将C ++ for Python的多个类包装在一起

  14. 14

    如何最好地将针对多个微服务的搜索服务与API网关集成在一起

  15. 15

    如何遍历元素中的每个单词,然后有条件地包装匹配项?

  16. 16

    sqlite3如何有条件地更改联接表中的字段(使用CASE..END和JOIN一起使用)?

  17. 17

    如何有条件地包装React组件?

  18. 18

    Razor语法-如何有条件地包装一些内部HTML

  19. 19

    使用Python API有条件地更新ElasticSearch文档

  20. 20

    使用React-Query挂钩有条件地调用API

  21. 21

    如何使swipejs与响应DOM一起使用?

  22. 22

    有条件地将字符串粘贴在一起

  23. 23

    Python; 有条件地将两个列表放在一起

  24. 24

    如何将条件Required Attribute放入类属性以与WEB API一起使用?

  25. 25

    在DOM准备就绪之前有条件地加载HTML元素

  26. 26

    MustacheJS有条件地显示DOM

  27. 27

    如何有条件地将元素插入列表?

  28. 28

    如何有条件地将元素添加到 std::array - C++11

  29. 29

    将jQuery与Shadow dom一起使用

热门标签

归档