Это продолжение моего предыдущего вопроса.
Я не могу разобраться с XSLT, чтобы сделать следующее. У меня есть HTML-код с одним или несколькими тегами <ul>. Теги <li> могут содержать теги <a>. Я хочу удалить любой тег <li>, если он содержит привязку, в которой href соответствует определенному шаблону.
Пример:
<ul>
<li><a href = "/some/old/path">One</a></li>
<li><a href = "/other/old/path">Two</a></li>
<li><a href = "/some/older/path">Three</a></li>
<li><a href = "/other/older/path">Four</a></li>
</ul>
Я хочу удалить строки <li>, в которых href содержит older, чтобы результат был таким:
<ul>
<li><a href = "/some/old/path">One</a></li>
<li><a href = "/other/old/path">Two</a></li>
</ul>
Строки, которые я хочу удалить, могут быть в любом порядке и разбросаны по нескольким тегам <ul>. Я в порядке, если в итоге у меня останется пустая пара <ul></ul> (но бонусные баллы, если такой полученный пустой список можно легко удалить). <li> теги, не содержащие привязки или содержащие несовпадающую привязку, следует оставить как есть.
Я приблизился к следующему:
<xsl:template match = "li/a[contains(@href, 'older')]">
</xsl:template>
но остается открытие <li>:
<ul>
<li><a href = "/some/old/path">One</a></li>
<li><a href = "/other/old/path">Two</a></li>
<li>
<li>
</ul>
Как мне избавиться от всей строки <li>?
Вот полный HTML-код, с которым я работаю:
<html>
<head>
<!-- lots of stuff I don't care about -->
</head>
<body>
<div>
<!-- lots of stuff I don't care about -->
<div>
<!-- lots of stuff I don't care about -->
<div id = "key_div">
<div id = "ignore_this">
<!-- lots of stuff I don't care about -->
</div>
<p>More junk I don't want</p>
<p>Even more junk I don't want</p>
<h2><span class = "someClass" id = "someID">Header</span></h2>
<p>Stuff I want to keep</p>
<!-- A lot of stuff I want to keep -->
<p>More stuff I want to keep</p>
<ul>
<li><a href = "/some/old/path">One</a></li>
<li><a href = "/some/old/other">Two</a></li>
<li><a href = "/some/older/path">Three</a></li>
<li><a href = "/some/older/other">Four</a></li>
</ul>
<ul>
<li>Leave this as-is</li>
</ul>
</div>
<!-- lots of stuff I don't care about -->
</div>
<!-- lots of stuff I don't care about -->
</div>
</body>
</html>
А вот XSLT:
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "html" indent = "yes" encoding = "utf-8"/>
<xsl:template match = "/html">
<html>
<head>
<title></title>
</head>
<body>
<xsl:apply-templates select = "//div[@id='key_div']/h2"/>
</body>
</html>
</xsl:template>
<xsl:template match = "h2">
<h1>
<xsl:value-of select = "." />
</h1>
<xsl:apply-templates select = "following-sibling::*"/>
</xsl:template>
<!-- My failed attempt to remove certain li lines -->
<xsl:template match = "li/a[contains(@href, 'older')]">
</xsl:template>
<xsl:template match = "@*|node()">
<xsl:copy>
<xsl:apply-templates select = "@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Мой текущий результат:
<html>
<head>
<meta http-equiv = "Content-Type" content = "text/html; charset=utf-8">
<title></title>
</head>
<body>
<h1>Header</h1>
<p>Stuff I want to keep</p>
<p>More stuff I want to keep</p>
<ul>
<li><a href = "/some/old/path">One</a></li>
<li><a href = "/some/old/other">Two</a></li>
<li>
<li>
</ul>
<ul>
<li>Leave this as-is</li>
</ul>
</body>
</html>
Мне просто нужно придумать, как удалить полную строку <li> для соответствующих hrefs.






С:
match = "li/a[contains(@href, 'older')]"
вы выбираете элемент a.
Попробуйте изменить его на:
match = "li[contains(a/@href, 'older')]"
(Непроверено, и, честно говоря, я даже не просматривал ваш полный XSLT.)
Ответ @DanielHaley сработал для конкретного примера, который я опубликовал. Оказывается, мои реальные потребности были немного сложнее, и его ответ привел к тому, что при обновлении условия было отфильтровано больше тегов <li>, чем ожидалось.
В моем немного более сложном случае я могу использовать такие привязки, как:
<ul>
<li><a href = "/some/path/old">One</a></li>
<li><a href = "/other/path/older">Two</a></li>
<li><a href = "/different/path/young">Two</a></li>
</ul>
и я хочу сохранить только привязки «старые». И моя версия XSLT (macOS 14) не поддерживает функцию ends-with. Если бы это было так, я мог бы использовать:
match = "li[not(ends-with(a/@href, 'old'))]"
Из-за отсутствия ends-with мне нужно совпадение типа:
match = "li[not(contains(a/@href, 'old')) or contains(a/@href, 'older')]
Но это также отфильтровывает любой тег <li>, который не содержит привязки.
Следующее изменение сработало для моего полного случая:
<xsl:template match = "li[a[not(contains(@href, 'old')) or contains(@href, 'older')]]" />
Теперь это фильтрует только теги <li>, у которых есть тег <a> со значением href, которое не заканчивается на "old".
@michael.hor257k Но цель состоит в том, чтобы оставить только те, которые заканчиваются на «старый». Поэтому я бы не хотел удалять ваш пример. Я думаю, вы имеете в виду, что мой ответ удалит этот пример, хотя на самом деле я бы этого не хотел. Возможно, но на самом деле это не тот случай, который мне нужно рассматривать в моем реальном случае использования. В любом случае, я, скорее всего, заменю свой обходной путь ends-with на ваш. Это проще и менее запутанно.
моя версия XSLT (macOS 14) не поддерживает
ends-withфункция. Если бы это было так, я мог бы использовать:
match = "li[ends-with(a/@href, 'old')]"
Вот одна из возможных реализаций ends-with() в XSLT 1.0:
<xsl:template match = "li[contains(concat(a/@href, '…'), 'old…')]"/>
Ах, я подумал, что должен быть более умный обходной путь из-за отсутствия ends-with. Хорошо знать.
Кстати, поскольку я хочу сохранить только узлы <li> с «href», оканчивающимся на «old», для этого нужен not( ) вокруг contains( ). Я пропустил not в своем ответе. Зафиксированный.
Я сформулировал свой ответ (а также комментарий к вашему вопросу) в свете отрывка, процитированного из вашего ответа (который вы теперь изменили). Я надеюсь, что вы будете знать, как внести необходимые коррективы.
P.S. Если вы используете процессор libxslt XSLT, входящий в состав macOS, включите тег xslt-1.0 во все вопросы по XSLT (рядом с тегом xslt). Тег libxslt также может быть полезен, так как этот процессор поддерживает большое количество функций расширения.
Спасибо за предложение тега. У меня мало опыта работы с XSLT (очевидно), и я не учел, что существуют разные версии.
Ваше выражение НЕ удалит
<li><a href = "/any/older/path/old">xyz</a></li>, несмотря на то, что значениеhrefзаканчивается на «старый».