Как выбрать прародителя узла с помощью xslt - PullRequest
7 голосов
/ 09 сентября 2010

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

Я пытался использовать:

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

17 голосов
/ 09 сентября 2010

Я пытался использовать:

<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]
4 голосов
/ 09 сентября 2010

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

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

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

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

Рассмотрим этот ввод (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 label, я бы использовал это:

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>

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...