访问 HTMLRewriter 中的嵌套元素 - Cloudflare Workers

Access nested elements in HTMLRewriter - Cloudflare Workers

我必须在 Cloudflare worker 中使用 HTMLRewriter 访问嵌套元素。

例子

<div data-code="ABC">
   <div class="title">Title</div>
   <div class="price">9,99</div>
</div>
<div data-code="XYZ">
   <div class="title">Title</div>
</div>

我正在考虑使用多个 .on() 但顺序没有保留,因为缺少一些 .price 并且我无法正确合并来自 codeHandler 和 PriceHandler 的结果

await new HTMLRewriter().on("[data-code]", codeHandler)
                        .on(".price", priceHandler)
                        .transform(response).arrayBuffer()

我正在考虑多次迭代 new HTMLRewriter() 但可读流被锁定。

当前代码

工人

class codeHandler {
    constructor() {
        this.values = []
    }

    element(element) {
        let data = {
            code: element.getAttribute("data-code"),
            title: element.querySelector(".title").innerText, <--
            price: element.querySelector(".price").innerText, <--- HERE
        }
        this.values.push( data )
    }
}


const url = "https://www.example.com"

async function handleRequest() {

  const response = await fetch(url)

   const codeHandler = new codeHandler()
   await new HTMLRewriter().on("[data-code]", codeHandler).transform(response).arrayBuffer()
    
    
   console.log(codeHandler.values)

    const json = JSON.stringify(codeHandler.values, null, 2)


    return new Response(json, {
        headers: {
        "content-type": "application/json;charset=UTF-8"
        }
    })  

}

addEventListener("fetch", event => {
  return event.respondWith(handleRequest())
})

快速查看文档后,似乎 element objects in the HTMLRewriter API 当前受到限制,无法按照您希望的方式访问子项。

似乎处理程序 运行 的顺序与文档中出现的顺序相同,这意味着对于您的用例,您可以跟踪当前元素并在该上下文中添加数据.您可以使用闭包使用不同的处理程序来访问相同的数据(在本例中为 values),如下所示:

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request))
});

async function handleRequest(request) {
  var values = [];
  var response = await fetch(request);
  function addToLast(attr, text) {
    var lastIndex = values.length - 1;
    if (lastIndex < 0) {
      // this shouldn't happen, since there should always have been
      // an object created by the parent [data-code] div
      return;
    }
    // need to add them to the previous value, just in case if there
    // are multiple text chunks
    values[lastIndex][attr] = (values[lastIndex][attr] || '') + text;
  }
  await new HTMLRewriter()
    .on("[data-code]", { 
      element(element) { 
        values.push({
          code: element.getAttribute("data-code")
        });
      },
      text(text) {
        addToLast('body', text.text);
      }
    })
    .on("[data-code] .title", {
      text(text) {
        addToLast('title', text.text);
      }
    })
    .on("[data-code] .price", {
      text(text) {
        addToLast('price', text.text);
      }
    })
    .transform(response).arrayBuffer();
  const json = JSON.stringify(values, null, 2)
  return new Response(json, {
    headers: {
      "content-type": "application/json;charset=UTF-8"
    }
  });
}

另请注意,您可以使用 descendant combinator(例如 [data-code] .title)来确保处理的唯一 .title div 是带有 [data-code] 的元素的子元素.