2010-09-09 3 views
7

Я в ситуации, когда я могу проверить только для дочернего узла, но мне нужно применить теги к бабушке дедушки этого дочернего узла.Как выбрать grandparent узла с помощью xslt

Я попытался с помощью:

<xsl:call-template name="grandparent" select="parent::parent::node()"/> 

и:

<xsl:call-template name="grandparent" select="ancestor::node [@nameofgrandparentnode]"/> 

Но ни работы.

Уровень узла grandparent не фиксирован, поэтому я полагаю, что я не могу использовать [@ level = #]. Любые идеи о том, как его выбрать, будут очень признательны.

EDIT: - Эта часть была размещена как новый вопрос:

xslt select grandparent node depending on an attribute value of its grandchild node

Выбор узла с использованием предложения снизу работал. Благодаря! Однако мне также нужно проверить атрибут дедушки или внука.

Я пробовал:

<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».

Я что-то упустил?

+0

Хороший вопрос (+1). См. Мой ответ для ряда выражений XPath, которые вы можете использовать в инструкции ''. –

+0

@highlightall Отредактированная часть не ясна. Пожалуйста, предоставьте полный (но как можно более короткий) XML-документ и полную таблицу стилей XSLT (опять же, как можно короче), которые воспроизводят вашу проблему. Предпочтительно спросите об этом в новом вопросе. –

+0

@highlightall: Также 'Даже для узлов внуков, значение атрибута которых не равно 'attrValue', не может быть истинным с этим шаблоном' grandparentnode [*/*/@ grandchildattr = 'attrValue'] ' – 2010-09-10 19:21:41

ответ

17

Я попытался с помощью:

<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] 
+0

+1 для сокращенного gradparent Выражение XPath. – 2010-09-09 13:00:55

+0

работал - спасибо! – highlightall

+0

@highlightall: Рад, что это сработало. Здесь в SO благодарность выражается путем принятия ответа. Подсказка: просто нажмите на галочку рядом с ответом. :) –

4

Я нахожусь в ситуации, когда я могу только тест для дочернего узла, но я должны применять теги к дедушке бабушки этого дочернего узла.

XSLT не является процедурным программированием, поэтому вам нужно думать о вещах немного по-другому.

Если я правильно понял, вы хотите добавить новые теги (дополнительные дочерние элементы или атрибуты?) В свой XML, но вы хотите добавить их к предку, когда найдете определенного потомка. Ваш примерный код пытается настроить таргетинг на дедушку, когда вы сталкиваетесь с ребенком. К сожалению, это может быть слишком поздно.

Возможно, вам потребуется ввести новый элемент/атрибут, когда движок встречает элемент, который вы хотите изменить (дедушка в вашем случае), а не когда он встречает ребенка, который соответствует условию (или вы будете в конечном итоге добавление элементов или атрибутов для ребенка)

Consider this input (прародитель = «альбом», внучат = «метка»):

<?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> 

Output (вручную отформатирован):

<?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> 

Некоторые песочница тестовые ресурсы:

+1

@Bert F: +1 для хорошего ответа и объяснения правильного подхода. – 2010-09-09 12:59:39

+0

@Alejandro - Спасибо - проверьте эти тестовые ресурсы - я нахожу их чрезвычайно удобными и полезными для экспериментов. –

+1

Очень полезный пример кода. Благодаря! – highlightall

Смежные вопросы