Как вырезать HTML-файл (удалить что-либо за пределами двух тегов)? - PullRequest
0 голосов
/ 07 июня 2018

Когда это мой пример HTML-документа:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>title</title>
  </head>
  <body>
    <iframe></iframe>
    <div class="text">TEST</div>
    <div id="trend" data-app="openableBox" class="box sub-box">
        <div class="box-header">
            <h1><span>Highlights</span></h1>
        </div>
    </div>
  </body>
</html>

Как мне извлечь

<iframe></iframe>
<div class="text">TEST</div>

, отбросив все до <iframe> и после (начиная с) <div id="trend">?

Спасибо, если вы могли бы помочь мне.

Ответы [ 2 ]

0 голосов
/ 10 июня 2018

Вот решение, которое решает общую проблему, предполагая, что нужно выбрать диапазон элементов на основе «линеаризации» HTML.Это решение использует pup для преобразования HTML в JSON, а затем использует для выполнения линеаризации, выделения и преобразования обратно в HTML.

program.jq

Идея состоит в том, чтобы «линеаризовать» HTML, рекурсивно поднимая дочерние элементы на верхний уровень:

# Emit a stream by hoisting .children recursively.
# It is assumed that the input is an array, 
# and that .children is always an array.
def hoist:
  .[]
  | if type == "object" and has("children")
    then del(.children), (.children | hoist)
    else .
    end;

def indexof(condition):
  label $out
  | foreach .[] as $x (null; .+1;
      if ($x|condition) then .-1, break $out else empty end)
    // null;

# Reconstitute the HTML element
def toHtml:
  def k: . as $in | (keys_unsorted - ["tag", "text"])
  | reduce .[] as $k (""; . + " \($k)=\"\($in[$k])\"");
  def t: if .text then .text else "" end;
  "<\(.tag)\(k)>\(t)</\(.tag)>"
  ;

# Linearize and then select the desired range of elements
[hoist]
| indexof( .tag == "iframe") as $first
| indexof( .tag == "div" and .id=="trend") as $last
| .[$first:$last]
| .[]
| toHtml

Вызов:

pup 'json{}' < input.html | jq -rf program.jq

Вывод:

<iframe></iframe>
<div class="text">TEST</div>
0 голосов
/ 07 июня 2018

При работе с данными HTML / XML из командной строки - следует использовать правильный анализатор HTML / XML.
xmllint является одним из таких.

xmllint --html --xpath '//body/*[self::iframe or self::div[@class="text"]]' input.html

Выход:

<iframe></iframe><div class="text">TEST</div>
...