Я пытаюсь заменить экземпляры уникальной строки в группе файлов, сканируя содержимое узлов с помощью Nokogiri, а затем выполняя gsub
. Я сохраняю часть строки на месте и превращаю ее в тег привязки. Тем не менее, большинство узлов имеют разную форму разметки в содержимом, а не просто строки. Например, допустим, у меня есть файл, подобный этому:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html>
<head>
<title>Title</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div>
<p class="header"><<2>>Header</p>
<p class="paragraph">
<p class="text_style">Lorem ipsum blah blah blah. <<3>> Here is more content. <span class="style">Preserve this.</span> Blah blah extra text.</p>
</div>
</body>
</html>
В документе есть числа, окруженные <<
и >>
. Я хочу взять значение числа и преобразовать его в тег вроде этого: <a id='[#]'/>
, но я хочу сохранить HTML разметку других элементов в том же разделе, то есть <span class="style">Preserve this.</span>
.
Вот все, что я пробовал:
file = File.open("file.xhtml") {|f| Nokogiri::XML(f)}
file.xpath("//text()").each { |node|
if node.text.match(/<<([^_]*)>>/)
new_content = node.text.gsub(/<<([^_]*)>>/,"<a id=\"\\1\"/>")
node.parent.inner_html = new_content
end
}
gsub
работает правильно, но поскольку он использует метод .text
, любая разметка игнорируется и эффективно стирается. В этом случае деталь <span class="style">Preserve this.</span>
полностью удаляется. (К вашему сведению, я использую метод .parent
, потому что, если я просто делаю node.inner_html = new_content
, я получаю эту ошибку: add_child_node': cannot reparent Nokogiri::XML::Element there (ArgumentError)
.)
Если я делаю это вместо этого:
new_content = node.text.gsub(/<<([^_]*)>>/,"<a id=\"\\1\"/>")
node.content = new_content
символы не экранированы должным образом: файл заканчивается <a id="3"/>
вместо <a id="3"/>
.
Я попытался использовать методы CSS вместо этого, например:
file.xpath("*").each { |node|
if node.inner_html.match(/<<([^_]*)>>/)
new_content = node.inner_html.gsub(/<<([^_]*)>>/,"<a id=\"\\1\"/>")
node.inner_html = new_content
end
}
The gsub
работает, разметка сохраняется, а замененные теги экранируются правильно. Но теги <head>
и <body>
удаляются, что приводит к неверному файлу:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Title</title>
<link href="style.css" rel="stylesheet" type="text/css"/>
<div>
<p class="header"><a id="2"/>Header</p>
<p class="paragraph">
</p><p class="text_style">Lorem ipsum blah blah blah. <a id="3"/> Here is more content. <span class="style">Preserve this.</span> Blah blah extra text. </p>
</div>
</html>
Я подозреваю, что это как-то связано с тем, что я перебираю все узлы (file.css("*")
), что также является избыточным, поскольку родительский узел сканируется в дополнение к его дочерним узлам.
Я просмотрел сеть, но не могу найти никаких решений для этого. Я просто хочу иметь возможность менять уникальный текст, сохраняя разметку и правильно ее кодируя. Есть ли что-то очень очевидное, что я здесь скучаю?