Удалить тег HTML, связанный с классом
Я заставляю себя научиться писать сценарии исключительно в AppleScript, но в настоящее время я сталкиваюсь с проблемой при попытке удалить определенный тег с помощью класса. Я пытался найти надежную документацию и примеры, но в настоящее время она кажется очень ограниченной.
Вот HTML-код, который у меня есть:
<p>Bacon ipsum dolor amet pork chop landjaeger short ribs boudin short loin jowl <span class="foo">shoulder</span> biltong shankle capicola drumstick pork loin rump spare ribs ham hock. <span class="bar">Pig brisket</span> jowl ham pastrami <span class="foo">jerky</span> strip steak bacon doner. Short loin leberkas jowl, filet mignon turducken chicken ribeye shank tail swine strip steak pork loin sausage. Frankfurter ground round porchetta, pork short ribs jowl alcatra flank sausage.</p>
То, что я пытаюсь сделать, это удалить определенный класс, чтобы он удалил <span class="foo">
, результат:
<p>Bacon ipsum dolor amet pork chop landjaeger short ribs boudin short loin jowl shoulder biltong shankle capicola drumstick pork loin rump spare ribs ham hock. <span class="bar">Pig brisket</span> jowl ham pastrami jerky strip steak bacon doner. Short loin leberkas jowl, filet mignon turducken chicken ribeye shank tail swine strip steak pork loin sausage. Frankfurter ground round porchetta, pork short ribs jowl alcatra flank sausage.</p>
Я знаю как это сделать с do shell script
и через терминал, но я хочу узнать, что доступно через словарь AppleScript.
В ходе исследования мне удалось найти способ для анализа всех тегов HTML с помощью:
on removeMarkupFromText(theText)
set tagDetected to false
set theCleanText to ""
repeat with a from 1 to length of theText
set theCurrentCharacter to character a of theText
if theCurrentCharacter is "<" then
set tagDetected to true
else if theCurrentCharacter is ">" then
set tagDetected to false
else if tagDetected is false then
set theCleanText to theCleanText & theCurrentCharacter as string
end if
end repeat
return theCleanText
end removeMarkupFromText
но это удаляет все теги HTML, и это не то, что я хочу. Ища SO, я смог найти, как извлечь теги из исходного кода HTML с помощью AppleScript, но я не собираюсь анализировать файл.
Я знаком с BBEdit's Balance Tags
известный как Balance
в выпадающем списке, но когда я бегу:
tell application "BBEdit"
activate
find "<span class=\"foo\">" searching in text 1 of text document "test.html" options {search mode:grep, wrap around:true} with selecting match
balance tags
end tell
он становится жадным и захватывает всю строку между первым тегом и вторым последним закрывающим тегом с текстом между ними вместо того, чтобы изолировать себя от первого тега с его текстом.
Дальнейшие исследования в словаре под tag
Я столкнулся find tag
что я мог сделать: set spanTarget to (find tag "span" start_offset counter)
затем нацелить тег с классом |class| of attributes of tag of spanTarget
и использовать balance tags
но я все еще сталкиваюсь с той же проблемой, что и раньше.
Так в чистом AppleScript, как я могу удалить тег, связанный с классом, не будучи жадным?
3 ответа
Я полагаю, что ответ Рона - хороший подход, но если вы не хотите использовать регулярные выражения, этого можно достичь с помощью приведенного ниже кода. Я не собирался публиковать его после того, как увидел, что Рон ответил, но я уже создал его, поэтому решил, что по крайней мере дам вам второй вариант, так как вы пытаетесь учиться.
on run
set theHTML to "<p>Bacon ipsum dolor amet pork chop landjaeger short ribs boudin short loin jowl <span class=\"foo\">shoulder</span> biltong shankle capicola drumstick pork loin rump spare ribs ham hock. <span class=\"bar\">Pig brisket</span> jowl ham pastrami <span class=\"foo\">jerky</span> strip steak bacon doner. Short loin leberkas jowl, filet mignon turducken chicken ribeye shank tail swine strip steak pork loin sausage. Frankfurter ground round porchetta, pork short ribs jowl alcatra flank sausage.</p>"
set theHTML to removeTag(theHTML, "<span class=\"foo\">", "</span>")
end run
on removeTag(theText, startTag, endTag)
if theText contains startTag then
set AppleScript's text item delimiters to {""}
set AppleScript's text item delimiters to startTag
set tempText to text items of (theText as string)
set AppleScript's text item delimiters to {""}
set middleText to item 2 of tempText as string
if middleText contains endTag then
set AppleScript's text item delimiters to endTag
set tempText2 to text items of (middleText as string)
set AppleScript's text item delimiters to {""}
set newString to implode(tempText2, endTag)
set item 2 of tempText to newString
end if
set newString to implode(tempText, startTag)
removeTag(newString, startTag, endTag) -- recursive
else
return theText
end if
end removeTag
on implode(parts, tag)
set newString to items 1 thru 2 of parts as string
if (count of parts) > 2 then
set newList to {newString, items 3 thru -1 of parts}
set AppleScript's text item delimiters to tag
set newString to (newList as string)
set AppleScript's text item delimiters to {""}
end if
return newString
end implode
Вы можете использовать регулярное выражение в find
команда для BBEdit или TextWrangler:
Чтобы выбрать тег (Non-Greedy), используйте эту команду:
find "<span class=\"foo\">.+?</span>" searching in text 1 of text document 1 options {search mode:grep, wrap around:true} with selecting match
Информация от .+?</span>
шаблон:
.
соответствует любому символу (кроме разрыва строки)+
означает одно или несколько повторений любого символа?
означает не жадные квантификаторы- Таким образом, шаблон соответствует открытию
span
тег, за которым следует одно или несколько вхождений любого символа, кроме возврата, с последующим закрытиемspan
тег, не жадный квантификатор достигает желаемых результатов, не давая BBEdit обойти закрытие</span>
тег и сопоставление нескольких тегов.
Чтобы соответствовать шаблону через разрывы строк, просто поместите (?s)
в начале шаблона, вот так:
find "(?s)<span class=\"foo\">.+?</span>" searching in text 1 of text document 1 options {search mode:grep, wrap around:true} with selecting match
- Команда соответствует тегу без перевода строки:
<span class="foo">shoulder</span>
- Или команда сопоставляет тег с разрывом строки:
<span class="foo">shoulder
</span>
- Или команда сопоставляет тег с несколькими строками:
<span class="foo">shoulder
xxxx
yyyy
zzzz</span>
В AppleScript вы можете использовать команду замены (BBEdit или TextWrangler), чтобы найти шаблон и удалить все совпадающие строки, как это
replace "(?s)<span class=\"foo\">.+?</span>" using "" searching in text 1 of text document 1 options {search mode:grep, wrap around:true}
Это работа для регулярных выражений, которые доступны через использование поддерживаемого в настоящее время моста AppleScriptObjC. Вставьте этот код в Script Editor и запустите его:
use AppleScript version "2.5" -- for El Capitan or later
use framework "Foundation"
use scripting additions
on stringByMatching:thePattern inString:theString replacingWith:theTemplate
set theNSString to current application's NSString's stringWithString:theString
set theOptions to (current application's NSRegularExpressionDotMatchesLineSeparators as integer) + (current application's NSRegularExpressionAnchorsMatchLines as integer)
set theExpression to current application's NSRegularExpression's regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value)
set theResult to theExpression's stringByReplacingMatchesInString:theNSString options:theOptions range:{location:0, |length|:theNSString's |length|()} withTemplate:theTemplate
return theResult as text
end stringByMatching:inString:replacingWith:
set theHTML to "<p>Bacon ipsum dolor amet pork chop landjaeger short ribs boudin short loin jowl <span class='foo'>SHOULDER</span> biltong shankle capicola drumstick pork loin rump spare ribs ham hock. <span class='bar'>PIG BRISKET</span> jowl ham pastrami <span class='foo'>JERKY</span> strip steak bacon doner. Short loin leberkas jowl, filet mignon turducken chicken ribeye shank tail swine strip steak pork loin sausage. Frankfurter ground round porchetta, pork short ribs jowl alcatra flank sausage.</p>"
set modifiedHTML to its stringByMatching:"<span .*?>(.*?)</span>" inString:theHTML replacingWith:"$1"
Это работает с хорошо отформатированным HTML, но, как указал пользователь foo выше, браузер может работать с плохо отформатированным HTML, но вы, вероятно, не можете.