2012-06-14 1 views
2

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

<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="SP" elem8="MC" elem9="DS" elem10="DA" elem11="16"/> 

мне нужен выход, чтобы быть «DA», если какой-либо атрибут «DA», или значение следующего атрибута, если какой-либо атрибут «BA» (то есть, если elem7 = «BA elem8 =» 03" Я хочу, чтобы выход «03»)

там нет опасности нескольких матчей, так что если атрибут «BA», то не будет никакого атрибута «DA», но значения могут произойти в любом элементе

I Я просмотрел атрибут :: tag, но я не уверен, что это удовлетворит мои потребности.

любая помощь с благодарностью

+1

Хмм, полагаясь на порядок атрибутов в вашем XML-входе, как правило, это трясет. См. Http://stackoverflow.com/questions/2287861/xslt-display-attributes-in-specific-order. В любом случае, я не считаю, что оси XSL, которые проверяют предварительно/просекательные узлы, могут применяться к атрибутам. – Utkanos

+0

Имена атрибутов всегда будут elem1, elem2 и т. Д. Есть ли способ получить имя атрибута, а затем заменить числовые символы в конце? – Jaloopa

+0

Чтобы получить имя узла или атрибута, используйте 'name()' – Utkanos

ответ

3

я сделал предположение, что ваши атрибуты имеют название в виде elemN где N = 1,2,3 ..., и они упорядочены соответствующим образом.

Следующая XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
    <xsl:output method="text" /> 
    <xsl:template match="/SI"> 
     <xsl:choose> 
      <xsl:when test="some $i in @* satisfies $i='DA'"> 
       <xsl:text>DA</xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:variable name="attr" select="concat('elem', xs:decimal(substring-after(@*[.='BA']/name(), 'elem')) + 1)" /> 
       <xsl:value-of select="@*[name() = $attr]" /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

применяется к следующему входному XML:

<?xml version="1.0" encoding="UTF-8"?> 
<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="SP" elem8="MC" elem9="DS" elem10="DA" elem11="16" /> 

дает DA как выход.

и применяется к следующему XML:

<?xml version="1.0" encoding="UTF-8"?> 
<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="BA" elem8="03" elem9="DS" elem10="DAs" elem11="16" /> 

дает 03 как выход.

EDIT

Вот XSLT версии 1.0 (протестировано под Altova XMLSpy):

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" /> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="SI/@*" /> 
    </xsl:template> 

    <xsl:template match="@*"> 
     <xsl:choose> 
     <xsl:when test=". = 'DA'"> 
      <xsl:text>DA</xsl:text>  
     </xsl:when> 
     <xsl:when test=".='BA'"> 
      <xsl:variable name="attr" select="concat('elem', substring-after(name(), 'elem') + 1)" /> 
      <xsl:value-of select="/SI/@*[name() = $attr]" /> 
     </xsl:when> 
     <xsl:otherwise/> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Принято, поскольку оно решает проблему, и я нашел ее немного более читаемой, чем ответ @dimitre ниже, но мне удалось попасть в код C#, который генерирует XML и устанавливает более легкодоступный атрибут. – Jaloopa

+0

ли это полагается на версию 2.0? При попытке переменной в таблице стилей 1.0 я получаю следующую ошибку: Ожидаемый токен ')', found '('. ... (substring-after (@ * [. = 'TM']/name -> (<- -), 'elem')) + 1) – Jaloopa

+0

@Jaloopa: как вы можете видеть в заголовке таблицы стилей, это для XSLT 2.0. Вы не упоминали, что хотели решения XSLT 1.0 ... – Lukasz

2

I need my output to be "DA" if any attribute is "DA", or the value of the next attribute if any attribute is "BA" (i.e. if elem7="BA elem8="03" I want "03" output)

There is no danger of multiple matches, so if an attribute is "BA", there will be no "DA" attribute, but the values could occur in any element

Это одно выражение XPath производит требуемое значение:

string(/*/@*[. = 'DA'] 
     | 
     /*/@*[name() 
       = 
       concat('elem', substring-after(name(/*/@*[.='BA']), 'elem') +1)] 
     ) 

А вот полная трансформация:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:template match="/"> 
    <xsl:copy-of select= 
    "string(/*/@*[. = 'DA'] 
      | 
      /*/@*[name() 
        = 
        concat('elem', substring-after(name(/*/@*[.='BA']), 'elem') +1)] 
      )"/> 
</xsl:template> 
</xsl:stylesheet> 

Как можно видеть, это преобразование просто оценивает выражение XPath и копирует результат оценки на выходе.

Когда преобразование применяется на этот XML-документ (ваш второй случай):

<SI elem1="TI" 
    elem2="FN" 
    elem3="4099450222" 
    elem4="TM" 
    elem5="4094110000" 
    elem6="MT" 
    elem7="BA" 
    elem8="03" 
    elem9="DS" 
    elem10="DD" 
    elem11="16"/> 

результат является:

03 

Когда же преобразование применяется на первоначально предоставленный XML-документ (ваш 1-й случай):

<SI elem1="TI" 
    elem2="FN" 
    elem3="4099450222" 
    elem4="TM" 
    elem5="4094110000" 
    elem6="MT" 
    elem7="SP" 
    elem8="MC" 
    elem9="DS" 
    elem10="DA" 
    elem11="16"/> 

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

DA 

Объяснение:

Правильное использование XPath союза оператора |, а функции string(), substring-after(), name() и `concat().

+0

+1 от меня - короче моих! – Lukasz

+0

@ LukaszBaran: У вас тоже хорошо. Я лично предпочитаю избегать каких-либо условных инструкций. +1. –

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

  • Нет связанных вопросов^_^