Как выбрать прародителя узла с помощью xslt
Я нахожусь в ситуации, когда я могу тестировать только дочерний узел, но я должен применить теги к прародителю этого дочернего узла.
Я пытался использовать:
<xsl:call-template name="grandparent" select="parent::parent::node()"/>
а также:
<xsl:call-template name="grandparent" select="ancestor::node [@nameofgrandparentnode]"/>
Но ни один не работает.
Уровень родительского узла не является фиксированным, поэтому я полагаю, что я не могу использовать [@level=#]. Любые идеи о том, как выбрать его, будет принята с благодарностью.
РЕДАКТИРОВАТЬ: - Эта часть была опубликована как новый вопрос:
xslt выберите родительский узел в зависимости от значения атрибута своего внукового узла
Выбор узла с использованием предложений снизу работал. Спасибо! Тем не менее, мне также нужно проверить по атрибуту узла прародителя или внука.
Я пробовал:
<xsl:template name"one" match="grandparentnode">
<Tag1>
<xsl:apply-templates select="parentNode" />
</Tag1>
</xsl:template>
<xsl:template name="two" match="grandparentnode[*/*/@grandchildattr='attrValue']">
<Tag2>
<xsl:apply-templates select="parentNode" />
</Tag2>
</xsl:template>
Однако шаблон "два" всегда вызывается, а "" всегда вставляется. Даже для узлов внуков, значение атрибута которых не равно attrValue.
Я что-то здесь упускаю?
2 ответа
Я пытался использовать:
<xsl:call-template name="grandparent" select="parent::parent::node()"/>
а также:
<xsl:call-template name="grandparent" select="ancestor::node[@nameofgrandparentnode]"/>
Но ни один не работает.
Конечно, это не будет "работать", потому что <xsl:call-template>
инструкция не имеет select
атрибут!
Вы можете передать параметры используя <xsl:with-param>
дети <xsl:call-template>
инструкция, как это:
<xsl:call-template name="compute">
<xsl:param name="pAncestor" select="someExpression"/>
</xsl:call-template>
Для select
атрибут <xsl:with-param>
Используйте:
Для настоящего деда:
../..
для ближайшего предка элемента с именем someName
:
ancestor::someName[1]
для ближайшего элемента предка с именем, содержащимся в переменной $ancName
:
ancestor::*[name()=$ancName][1]
Я нахожусь в ситуации, когда я могу тестировать только дочерний узел, но я должен применить теги к прародителю этого дочернего узла.
XSLT не является процедурным программированием, поэтому вы должны думать о вещах немного по-другому.
Если я правильно понимаю, вы хотите добавить новые теги (дополнительные дочерние элементы или атрибуты?) В ваш XML, но вы хотите добавить его к предку, когда найдете конкретного потомка. Ваш пример кода, кажется, пытается нацелить бабушку и дедушку, когда вы сталкиваетесь с ребенком. К сожалению, это может быть слишком поздно.
Возможно, вам понадобится внедрить новый элемент / атрибут, когда движок натолкнется на элемент, который вы хотите изменить (прародитель в вашем случае), а не когда он встретит дочерний элемент, который соответствует условию (иначе вы в конечном итоге добавите элементы или атрибуты ребенку)
Рассмотрим этот ввод (grandparent="album", grandchild="label"):
<?xml version="1.0" encoding="UTF-8"?>
<album>
<title>Sgt. Pepper's Lonely Hearts Club Band</title>
<artist>The Beatles</artist>
<year>1967</year>
<labels>
<label>Parlophone</label>
<label>Capitol</label>
</labels>
</album>
Я хочу изменить album
на основе того, является ли определенный label
настоящее. Помните, что общий формат для таргетинга на узлы: target-node[target-condition]
, Чтобы изменить любой album
элементы, которые имеют Capitol
обозначить элемент внука, я бы использовал это:
album[*/label='Capitol']
Так что рассмотрите эту таблицу стилей, чтобы добавить новый атрибут и 2 новых дочерних элемента в album
Это соответствует моему состоянию:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="album[*/label='Capitol']">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="new-attribute">A Capitol Record</xsl:attribute>
<new-element1/>
<xsl:apply-templates select="node()"/>
<new-element2/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Вывод (отформатированный вручную):
<?xml version="1.0" encoding="UTF-8"?>
<album new-attribute="A Capitol Record">
<new-element1/>
<title>Sgt. Pepper's Lonely Hearts Club Band</title>
<artist>The Beatles</artist>
<year>1967</year>
<labels>
<label>Parlophone</label>
<label>Capitol</label>
</labels>
<new-element2/>
</album>
Некоторые тестовые ресурсы для песочницы:
- http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm
- Чтобы увидеть, на какие узлы на самом деле нацелено данное выражение XPath
- http://unindented.org/projects/xslt-tester-applet/run/
- Чтобы попробовать таблицу стилей