2012-05-10 6 views
2

У меня есть следующий XML-код:Получить различные значения в пределах конкретных атрибутов

<!-- language: xml --> 
<Stats> 
    <Stat> 
    <Data Name="Value">63.76</Data> 
    <Data Name="Entity">first</Data> 
    </Stat> 
    <Stat> 
    <Data Name="Value">51.23</Data> 
    <Data Name="Entity">second</Data> 
    </Stat> 
    <Stat> 
    <Data Name="Value">46.1</Data> 
    <Data Name="Entity">third</Data> 
    </Stat> 
    <Stat> 
    <Data Name="Value">61.21</Data> 
    <Data Name="Entity">first</Data> 
    </Stat> 
</Stats> 

Я хочу, чтобы фильтровать только там, где 'Data [@ Name =' Entity ']. Использование XPath: /Stats/Stat/Data[@Name="Entity"] возвращается: первого второго третьего первого

Но я хочу, чтобы результаты были уникальными. Поэтому я получаю только: first second third

EDIT: Мне нужно это для работы с версией xpath 1.0.

+0

Bouke Groeneschei j: Был ли мой ответ полезным или у вас все еще есть проблемы? –

+0

duplicate-> http://stackoverflow.com/questions/3016929/selecting-unique-records-in-xslt-xpath – rt2800

+0

Я видел это сообщение, однако - я не думаю, что этот дубликат. XML код есть: 63,76 первый Мой XML код: <Имя данных = "Значение"> 63,76 начато

ответ

3

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

/Stats/Stat 
    [Data/@Name='Entity' 
    and 
    not(Data[@Name='Entity'] = following-sibling::Stat/Data[@Name = 'Entity']) 
    ] 
    /Data[@Name='Entity'] 

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= 
     "/Stats/Stat 
      [Data/@Name='Entity' 
      and 
      not(Data[@Name='Entity'] = following-sibling::Stat/Data[@Name = 'Entity']) 
      ] 
      /Data[@Name='Entity'] 
     "/> 
</xsl:template> 
</xsl:stylesheet> 

, когда это преобразование применяется на следующий XML-документ (изготовитель cor recting не-хорошо сформированные при условии текста):

<Stats> 
    <Stat> 
    <Data Name="Value">63.76</Data> 
    <Data Name="Entity">first</Data> 
    </Stat> 
    <Stat> 
    <Data Name="Value">51.23</Data> 
    <Data Name="Entity">second</Data> 
    </Stat> 
    <Stat> 
    <Data Name="Value">46.1</Data> 
    <Data Name="Entity">third</Data> 
    </Stat> 
    <Stat> 
    <Data Name="Value">61.21</Data> 
    <Data Name="Entity">first</Data> 
    </Stat> 
</Stats> 

приведенное выше выражение XPath, вычисляется и выбранные узлы будут скопированы на выходе:

<Data Name="Entity">second</Data> 
<Data Name="Entity">third</Data> 
<Data Name="Entity">first</Data> 

Примечание: Если вы просто нужны текстовые узлы («первая», «вторая» и «третья»), просто используйте это единственное выражение XPath:

/Stats/Stat 
    [Data/@Name='Entity' 
    and 
    not(Data[@Name='Entity'] = following-sibling::Stat/Data[@Name = 'Entity']) 
    ] 
    /Data[@Name='Entity'] 
     /text() 
+0

Просто потрясающе! Большое спасибо за быстрый и точный ответ. Я искал это в течение долгого времени.Особенно последняя заметка сделала это - и XSLT - отличный бонус! –

+0

@BoukeGroenescheij: Добро пожаловать. Да, и XPath, и XSLT - это захватывающие, мощные и элегантные языки. –

3

Вам нужно указать версию XPath. В XPath 2.0, это тривиальное:

distinct-values(/Stats/Stat/Data/@Name) 
+0

Спасибо. Вы правы - извините, мне нужно это для XPath 1.0. –

+1

Кстати, приведенный выше код не дает желаемых результатов, так как он возвращает значение и сущность. После того, как вы изменили его на: distinct-values ​​(/ Stats/Stat/Data [@ Name = 'Entity]), он работает - теперь мне нужно преобразовать его в XPath версии 1.0 ... –

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