Я пытаюсь сопоставить набор определенных элементов, но только те, которые являются дочерними по отношению к другой структуре элементов (скажем, это ввод или выбор элементов только где-то внутри div
s с классом «особый соус» на них). Обычно это было бы просто до XPATH: мы могли бы объединить в скобки целевые дочерние элементы, например:
div[contains(@class, 'special-sauce')//(input | select)
Но именно здесь XSLT бросает вызов, когда мы пытаемся использовать это как сопоставление с шаблоном (по крайней мере, в Saxon):
<xsl:template match="div[contains(@class, 'special-sauce')//(input | select)">
{"error": "Файл xsl (/section-settings.xsl) не может быть проанализирован. Не удалось скомпилировать таблицу стилей. Обнаружена 1 ошибка.", "code": "TRANSFORM_ERROR", "location": null, "cause" : ["Неустранимая ошибка: токен \" (\ "здесь не допускается в шаблоне XSLT"]}
По сути, круглые скобки не разрешены как часть соответствия шаблону на основном уровне пути (очевидно, они по-прежнему отлично работают внутри условных выражений / и т. Д.).
Так что делать?
Что ж, технически использование объединения все еще может работать, но нам придется каждый раз повторять предок XPATH, поскольку мы не можем заключить в скобки дочерние элементы:
<xsl:template match="div[contains(@class, 'special-sauce')//input
| div[contains(@class, 'special-sauce')//select">
Это выполнимо (не очень красиво, но, конечно, мы справимся с этим! Разрывы строк могут работать здесь, чтобы помочь нашему здравомыслию) в нашем простом примере здесь, но это становится проблематичным с более сложным XPATH, особенно если бы объединение в скобках было в середине более длинного xpath или для множества элементов.
e.g.
div[contains(@class, 'major-mess')]/div[contains(@class, 'special-sauce')]//(dataset | optgroup | fieldset)//(button | option | label)
становится
a crazy mess.
Хорошо, это быстро становится менее подходящим вариантом в более сложных примерах. И хотя структурирование нашего XSLT по-другому может помочь (промежуточные совпадения, использование модальности и т. Д.), Остается вопрос:
Как мы можем изящно сопоставить шаблон, используя объединения отдельных дочерних элементов в более крупном шаблоне XPATH, когда скобки в скобках не работают?
Пример листа для первого примера:
<div class="special-sauce">
<input class="form-control" type="text" value="" placeholder="INHERITED:" />
<select class="form-control">
<option value="INHERITED: ">INHERIT: </option>
<option value=""></option>
</select>
<div class="radio">
<label>
<input type="radio" name="param3vals" value="INHERITED: " />
INHERIT:
</label>
</div>
</div>
<div class="not-special"><input type="text" id="contact-info-include-path" size="90">
<label>contact</label>
</input></div>
<div class="sad-panda"><input type="text" id="sidenav-include-path" size="90">
<label>sidenav</label>
</input></div>
Примечание: здесь предполагается, что преобразование идентичности выполняется как основной метод обработки входного документа.
Хотя есть и другие вопросы, на которые можно получить ответы, аналогичные, например, тому, который я даю ниже, я чувствовал, что контекст этих вопросов обычно был более общим (так что союз верхнего уровня был бы прекрасен в качестве их ответа без осложнений), более конкретными способами, которые не совпадают, или просто слишком разными. Отсюда и формат вопросов и ответов.
XSLT 1.0 против 2.0 против 3.0
Майкл Кей правильно отмечает в своем ответьте ниже, что, хотя исходный шаблон, использованный здесь, не работает в XSLT 1.0 или 2.0, он должен работать в (полностью) процессоре, совместимом с XSLT 3.0. В настоящее время я использую систему, использующую Saxon 9.3, которая технически является XSLT 2.0. Я просто хочу привлечь дополнительное внимание к этому ответу для тех, кто использует систему 3.0.
HeadPathExpression/*[self::name1 or self::name2 or self::name3]
? 17.09.2015