2012-05-11 2 views
1

У меня есть этот XML:Нужна помощь в XPath

<mappings>  
     <mapping>  
      <name iskey="true">234</name>  
      <aid iskey="true">bmz</aid>  
      <bid iskey="true">sim</bid>  
      <data>GSSS</data>  
     </mapping>  
     <mapping>  
      <aid iskey="true">bmz</aid>  
      <bid iskey="true">sim</bid>  
      <data>TS</data>  
     </mapping>  
     <mapping>  
      <aid iskey="true">bmz</aid> 
      <account>TS</account>  
     </mapping> 
    </mappings> 

Мне нужно, чтобы выбрать XPath узел, который имеет узел <aid iskey='true'>bmz</aid> и никакой другой узел, содержащий IsKey атрибут.

ответ

4

После несколько назад и вперед в комментариях, кажется, как вы хотите ухватить в mapping узла (или любой другой узел по этому вопросу), который имеет узел aid ребенка с определенными атрибутами и значением, но нет других дочерних узлов с атрибутом @iskey. Вы делаете это так:

//*[aid/@iskey='true' and aid/text()='bmz'][not(*[@iskey][local-name() != 'aid'])] 

Предикат говорит именно, что: имеет узел aid ребенка с этими значениями и не имеет дочерний узел с именем, отличным от aid, что случилось бы иметь атрибут @iskey.

Когда я запускаю этот простой тест таблицы стилей:

<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:copy-of select="//*[aid/@iskey='true' and aid/text()='bmz'][not(*[@iskey][local-name() != 'aid'])]"/> 
    </xsl:template> 
</xsl:stylesheet> 

от входного документа я получаю следующее в ответ:

<mapping> 
    <aid iskey="true">bmz</aid> <!-- I need this node --> 
    <account>TS</account> 
</mapping> 

UPDATE если вы хотите ухватить узлов что только один дочерний узел с @iskey, вы можете сойти с рук:

//*[count(*[@iskey]) = 1] 

я включил его в моей тестовой таблицы стилей и он произвел тот же ожидаемый результат:

<mapping> 
    <aid iskey="true">bmz</aid> <!-- I need this node --> 
    <account>TS</account> 
</mapping> 
+0

не работает. Сначала возвращает null, а второй возвращает первый узел. Мне нужен последний узел из вышеупомянутого xml, имеющего только два тега. –

+0

Есть три узла, которые ' bmz'.если вам нужен последний, вы можете сделать это так: '// help [@ iskey = 'true' и text() = 'bmz'] [last()]' –

+0

'// help [@ iskey = 'true' и text() = 'bmz'] [last()] 'будет выбирать все последние узлы с указанными атрибутами своих родителей из этого xml. '// mapping [last()]/aid', вероятно, будет –

3

Используйте это короче и проще выражение XPath:

/*/* 
    [aid[@iskey='true' and .='bmz'] 
    and 
     not(*[not(self::aid)][@iskey]) 
     ] 

Объяснение:

Это простой, конкретный случай «Double Negation Principle ":)

XSLT - на основе проверки:

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

<xsl:template match="/"> 
    <xsl:copy-of select= 
    "/*/* 
    [aid[@iskey='true' and .='bmz'] 
    and 
     not(*[not(self::aid)][@iskey]) 
     ]"/> 
</xsl:template> 
</xsl:stylesheet> 

Когда это преобразование применяется на прилагаемом документе XML:

<mappings> 
    <mapping> 
     <name iskey="true">234</name> 
     <aid iskey="true">bmz</aid> 
     <bid iskey="true">sim</bid> 
     <data>GSSS</data> 
    </mapping> 
    <mapping> 
     <aid iskey="true">bmz</aid> 
     <bid iskey="true">sim</bid> 
     <data>TS</data> 
    </mapping> 
    <mapping> 
     <aid iskey="true">bmz</aid> 
     <account>TS</account> 
    </mapping> 
</mappings> 

выражение XPath вычисляется и выбранные элементы (только один в этом случае) копируются на выход:

<mapping> 
    <aid iskey="true">bmz</aid> 
    <account>TS</account> 
</mapping> 
+0

приятно. Чем больше я думаю об этом конкретном, тем больше я полагаю, что мы должны идти по принципу «generate-id()», а не «local-name()» или «self :: aid», чтобы избежать дублирования. Либо решение с именами узлов в нем будет содержать два или более '' childnodes –

+0

@PavelVeller: OP говорит «узел», потому что в его примере есть только один такой элемент. В общем, если есть несколько таких элементов, все они выбраны. В этом случае OP может добавить дополнительные ограничения, чтобы получить только один такой узел или тот, который также соответствует некоторым дополнительным требованиям. –

+0

@WaqarJanjua: Добро пожаловать. –

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