2017-02-14 23 views
0

Я хотел бы получить отдельные имена элементов из моего XML-файла с помощью XSLT-1.0.XSLT - Как получить отдельные имена элементов из XML?

XML:

<forms> 
    <form1> 
     <metadata> 
     <c1>some value</c1> 
     <c2>some value</c2> 
     </metadata> 
     <set> 
     <subset1> 
      <c3>some value</c3> 
      <c4>some value</c4> 
      <c5>some value</c5> 
     </subset1> 
     <subset2> 
      <c3>some value</c3> 
      <c4>some value</c4> 
      <c6>some value</c6> 
     </subset2> 
     </set>    
    </form1> 
    <form2> 
    ... 
    </form2> 
</forms> 

Мой результат должен выглядеть, как показано ниже, когда я прохожу имя формы в XSLT. Например, если я прохожу "Form1" он должен получить мне отдельные элементы данных, доступные внутри моей <form1> тега так:

c1, c2, c3, c4, c5, c6

Кроме того, Я попробовал этот XSLT и его возвращение этого:

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

    <xsl:template match="/"> 
    <xsl:for-each select= 
    "//*/*/*[not(../following::*/* 
         [not(name() = name(current()))] 
       ) 
      ]"> 
     <xsl:value-of select="concat(name(), ' ')"/> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Выход:

Set1, set2, subset1, subset2, c3 , С4, с6

Ожидаемый результат:

c1, c2, c3, c4, c5, c6

Кроме того, как передать мое имя формы (т.е. form1) моему XSLT?

+0

Что определяет «элемент данных»? –

+0

Я имел в виду только элемент (т. Е. Узлы ... , , и т. Д.) – user972255

+0

'set1' также является элементом. На какой основе это должно быть исключено? --- P.S. Какой процессор XSLT 1.0 вы будете использовать? Вы действительно можете использовать функцию расширения здесь, если хотите ограничить результат определенной ветвью. –

ответ

1

Получение списка различных наименований всех элементов во всем документе относительно просто - как показано в ответе Dan Field.

Ограничение списка элементами, которые являются либо детьми metadata, либо внуками set несколько сложнее.

Ограничение списка дополнительно включать только элементы, которые являются потомками определенного form, которые будут определены во время выполнения, является гораздо сложнее.

Рассмотрим следующую таблицу стилей:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:param name="selected-form-name">form1</xsl:param> 

<xsl:key name="data" match="*" use="name()" /> 

<xsl:template match="/forms"> 
    <xsl:variable name="selected-form" select="*[name()=$selected-form-name]"/> 
    <!-- all names in the selected form --> 
    <xsl:variable name="names-in-form"> 
     <xsl:for-each select="$selected-form/metadata/* | $selected-form/set/*/* " > 
      <name> 
       <xsl:value-of select="name()"/> 
      </name> 
     </xsl:for-each> 
    </xsl:variable> 
    <!-- distinct elements (by name), in the entire document --> 
    <xsl:variable name="distinct-by-name" select="//*[count(. | key('data', name())[1]) = 1]" /> 
    <output> 
     <xsl:for-each select="$distinct-by-name[name()=exsl:node-set($names-in-form)/name]"> 
      <item><xsl:value-of select="name()"/></item> 
     </xsl:for-each> 
    </output> 
</xsl:template> 

</xsl:stylesheet> 

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

XML

<forms> 
    <form1> 
     <metadata> 
     <c1>some value</c1> 
     <c2>some value</c2> 
     </metadata> 
     <set> 
     <subset1> 
      <c3>some value</c3> 
      <c4>some value</c4> 
      <c5>some value</c5> 
     </subset1> 
     <subset2> 
      <c3>some value</c3> 
      <c4>some value</c4> 
      <c6>some value</c6> 
     </subset2> 
     </set>    
    </form1> 
    <form2> 
     <metadata> 
     <c7>some value</c7> 
     <c8>some value</c8> 
     </metadata> 
     <set> 
     <subset3> 
      <c9>some value</c9> 
      <c7>some value</c7> 
     </subset3> 
     </set>    
    </form2> 
</forms> 

результат будет:

<?xml version="1.0" encoding="UTF-8"?> 
<output> 
    <item>c1</item> 
    <item>c2</item> 
    <item>c3</item> 
    <item>c4</item> 
    <item>c5</item> 
    <item>c6</item> 
</output> 

Чтобы выбрать требуемую форму, передайте параметр с именем selected-form-name в таблицу стилей с указанием имени формы. Если вы передадите строку "form2", результатом будет:

<?xml version="1.0" encoding="UTF-8"?> 
<output> 
    <item>c7</item> 
    <item>c8</item> 
    <item>c9</item> 
</output> 
+0

Отлично! Большое спасибо. – user972255

1

Вы можете создать ключ местных названий, а затем сделать что-то вроде этого:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" /> 
    <xsl:key name="elements" match="*" use="local-name()" /> 
    <xsl:template match="/"> 
    <xsl:for-each select="//*[count(.|key('elements', local-name())[1]) = 1]"> 
     <xsl:value-of select="local-name()" />, 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

В основном, делая Muenchian группировку против имен элементов.

+1

Чтобы получить ** точный ** выход, попробуйте ' ,' – zx485

+0

@ zx485 Это не логика обозначенный OP в комментариях. –

+0

@ Dan: Спасибо! Это не полностью отвечает на мой вопрос, но определенно мне очень помогло. – user972255