2013-04-05 3 views
1

В моем xml я хочу, чтобы определенные узлы menuitems/menuitem, которые будут находиться в разных произвольных положениях под его родительским элементом (я не хочу селектор жесткого кода).Как получить позицию узла на основе значения дочернего элемента

Возможно ли получить позицию узла menuitem, который имеет правильное значение в элементе имени под ним, что означает menuitems/menuitem/name. Короче: выбор menuitem, который имеет значение name под ним.

<one> 
    <menuitems> 
     <menuitem> <!-- I dont want this one --> 
     <name> 
      ... 
     </name> 
     </menuitem> 

     <menuitem> <!-- I want this one at position 2 under <one> --> 
     <name> 
      ... <!-- Based one correct name value here --> 
     </name> 
     </menuitem> 
    </menuitems> 

</one> 
<two> 
    <menuitems> 
    <menuitem> <!-- I want this one at position 1 under <two> --> 
     <name> 
      ... 
     </name> 
    </menuitem> 
    </menuitems> 
</two> 

я могу легко узнать, если один menuitem под menuitems имеет правильное name значение. Как так:

<xsl:value-of select="current()/menuitems/menuitem/name = 'OhYes'"></xsl:value-of> 

который будет возвращать true. Но в какой позиции это menuitem среди других menuitem, которые вернулись true? Выбор под одним и тем же родителем и на том же уровне.

Я хочу, чтобы избежать этого:

<xsl:if test="current()/menuitems/menuitem[1]/name = 'OhYes'"> .. </xsl:if> 
<xsl:if test="current()/menuitems/menuitem[2]/name = 'OhYes'"> .. </xsl:if> 
+0

Пожалуйста, напишите «рабочий» образец. То есть тот, который может быть создан для демонстрации того, что вы просите? – MattH

+0

@MattH Посмотреть сейчас. – gorn

+2

Вы действительно ищете место? Или вас просто интересует выбор определенного элемента «menuitem» на основе его дочернего элемента «name»? Если вы просто используете путь, например '// */menuitems/menuitem [name = 'OhYes']', вы выбираете элементы элемента. Если вы действительно хотите вывести позицию, используйте, например, ''. Если вам нужен полный код, рассмотрим, пожалуйста, точный тип (т. Е. Html или xml или текст) и содержимое результата, который вы хотите создать с помощью XSLT 2.0. –

ответ

0

Используйте этот:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:for-each select="/*/*/menuitems/menuitem[name='OhYes']"> 
    position: <xsl:text/> 
    <xsl:value-of select="count(preceding-sibling::menuitem) +1"/> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

** Когда это преобразование применяется на следующий документ XML: ... -> OhYes -> OhYes

разыскиваемый, правильный результат получается:

position: 2 
    position: 1 
+0

Да, правильный ответ - использовать предикаты 'current()/menuitems/menuitem [name = 'OhYes']'. Без цикла и получения позиции тогда не требуется. – gorn

+0

@gorn, Добро пожаловать –

0

Вы можете первые разделяющий из одного и двух контейнеров с использованием getElementsByTagName. Для каждого раздела (один, два) попробуйте выполнить итерацию по всем именам, создав массив, используя getElementsByTagName, а затем проверите каждый элемент, чтобы узнать, правильно ли это имя. Поскольку каждая позиция меню соответствует позиции имени под каждым заголовком (один, два), вы можете использовать аксессуар .parentNode на каждом совпадающем узле имени, чтобы вернуть узел menuitem, и индекс итератора, чтобы вернуть свою позицию.

Например, для XML кодекса

<one> 
    <menuitems> 
     <menuitem> <!-- I dont want this one --> 
     <name> 
      the incorrect name 
     </name> 
     </menuitem> 
    </menuitems> 

    <menuitems> 
     <menuitem> <!-- I want this one at position 2 --> 
     <name> 
      the correct name <!-- Based one correct name value here --> 
     </name> 
     </menuitem> 
    </menuitems> 
</one> 
<two> 
    <menuitems> 
    <menuitem> <!-- I want this one at position 1 --> 
     <name> 
      the correct name 
     </name> 
    </menuitem> 
    </menuitems> 
</two> 

Следующий код предупреждает индекс узлов имен (и родительский MENUITEM) в рамках текущего контейнера (один, два), что cotnain правильный текст имени в тег с надписью «правильное название»

names = new Array(); 

// Find the correct position for the menuitem under one 
one = document.getElementsByTagName("one")[0]; 

names = one.getElementsByTagName("name"); 

for (var i=0; i<names.length; i++){ 
    if (names[i].innerHTML.search("the correct name") >= 0) 
     alert("For one: Correct name found at name node index " + (i+1) + " and its parent menuitem is " + names[i].parentNode); 

    // names[i].parentNode is the reference to the menuitem in one that contains the correct name 
} 

// Find the correct position for the menuitem under two 
two = document.getElementsByTagName("two")[0]; 

names = two.getElementsByTagName("name"); 

for (var i=0; i<names.length; i++){ 
    if (names[i].innerHTML.search("the correct name") >= 0) 
     alert("For two: Correct name found at name node index " + (i+1) + " and its parent menuitem is " + names[i].parentNode); 

    // names[i].parentNode is the reference to the menuitem in one that contains the correct name 

} 

Я также создал скрипку в http://jsfiddle.net/nMN3j/1/, так что вы можете попробовать его, и посмотреть, как это работает.

Этот код предупредит, что в контейнере «один» тег menuitem был найден в позиции 2, который имеет правильную подзапись имени, но не в позиции 1, которая имеет неправильный подтег имени.

Для контейнера «два» код будет предупреждать, что элемент меню был найден в позиции 1, который имеет правильное имя.

Надеюсь, это поможет!

+0

Просто прочитайте вопрос еще раз. Вы также хотите, чтобы позиция элемента menuitem под правильным именем? – KernelPanik

+0

Мой первый пост не был точным. См. Мою отредактированную версию сейчас. – gorn

+0

Нет проблем, я обновил свой ответ и скрипку выше. Ура! – KernelPanik

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