2010-01-20 2 views
2

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

<tag> 
    <Keyword>Event: Some Text</Keyword> 
    <Keyword>Group: Some Text</Keyword> 
    <Keyword>Other: Some Text</Keyword> 
</tag> 

Я хотел бы желаемый выхода быть:

<tag> 
    <event> Some Text </event> 
    <group> Some Text </group> 
    <other> Some Text </other> 
</tag> 

Моего текущего XSL файл:

<xsl:for-each select="tag"> 
    <xsl:if test="starts-with(Keyword, 'Event: ')"> 
     <event> 
      <xsl:value-of select="substring-after(Keyword, 'Event: ')"/> 
     </event> 
    </xsl:if> 
    <xsl:if test="starts-with(Keyword, 'Group: ')"> 
     <group> 
      <xsl:value-of select="substring-after(Keyword, 'Group: ')"/> 
     </group> 
    </xsl:if> 
    <xsl:if test="starts-with(Keyword, 'Other: ')"> 
     <other> 
      <xsl:value-of select="substring-after(Keyword, 'Other: ')"/> 
     </other> 
    </xsl:if> 
</xsl:for-each> 

Токовый выход только показывает узел событий и не отображает остальные узлы:

<tag> 
    <event> Some Text </event> 
</tag> 

Я попытался переключением раздела «группы» с разделом «событий» в XSL, однако все дочерние узлы не отображаются, возможно, из-за упорядочение узлов ключевого слова во входном XML. Итак, как я могу читать все узлы ключевых слов и преобразовывать их в соответствующие новые узлы для отображения?

ответ

2

У вас есть только один элемент tag. Вы хотите перебрать все эти детей:

<xsl:for-each select="tag/*"> 

    <xsl:if test="starts-with(., 'Event: ')"> 
     <event> 
      <xsl:value-of select="substring-after(., 'Event: ')"/> 
     </event> 
    </xsl:if> 
    <xsl:if test="starts-with(., 'Group: ')"> 
     <group> 
      <xsl:value-of select="substring-after(., 'Group: ')"/> 
     </group> 
    </xsl:if> 
    <xsl:if test="starts-with(., 'Other: ')"> 
     <other> 
      <xsl:value-of select="substring-after(., 'Other: ')"/> 
     </other> 
    </xsl:if> 
</xsl:for-each> 

EDIT: добавлено еще одно решения (с использованием @ оригинальным решением Пьера).
Примечание значение XSL: имя атрибут элемента заворачивают в {} так, что она оценивается как Attribute Value Template, а не как символьная строка:

<xsl:template match="tag"> 
<xsl:apply-templates select="Keyword"/> 
</xsl:template> 

<xsl:template match="Keyword"> 
<xsl:element name="{normalize-space(substring-before(.,':'))}"> 
<xsl:value-of select="normalize-space(substring-after(.,':'))"/> 
</xsl:element> 
</xsl:template> 
+0

Большое вам спасибо ... это работает! – Hariz

+1

Вы должны посмотреть на решение @ Pierre и подумать о том, чтобы попытаться сделать больше совпадений с шаблонами, чем для каждого утверждения в вашем XSLT. Это своего рода другой способ делать вещи (декларативные или процедурные), которые иногда трудно понять, но это облегчит разработку и обслуживание. –

2

Вот мое решение. Вам не нужно создавать все эти если таковые заявления с использованием XSL: элемент

<xsl:template match="tag"> 
<xsl:apply-templates select="Keyword"/> 
</xsl:template> 

<xsl:template match="Keyword"> 
<xsl:variable name="tag" select="normalize-space(substring-before(.,':'))"/> 
<xsl:value-of select="concat('&lt;',$tag,'&gt;')" disable-output-escaping="yes"/> 
<xsl:value-of select="normalize-space(substring-after(.,':'))"/> 
<xsl:value-of select="concat('&lt;/',$tag,'&gt;')" disable-output-escaping="yes"/> 
</xsl:template> 
+0

+1 Гораздо более чистый. Я собирался добавить что-то подобное к моему ответу, но вы избили меня! –

+0

Хм говорит, что символ '(' не может быть включен в название элемента. – Hariz

+0

Ах ... Возможно, вы правы. Я изменил xsl: element на xsl: значение-с с помощью @ disable-output-escaping = 'yes'. – Pierre

3

@Pierre: Я понимаю, первый вопрос и ваше решение правильно;) Ваш путь для строительства XML элементы IMHO немного hackly. XSLT имеет специальный набор для динамического построения элементов xml. Таким образом, ваш шаблон матч = «Ключевое слово» может выглядеть следующим образом

<xsl:template match="Keyword"> 
    <xsl:variable name="tag" select="normalize-space(substring-before(.,':'))"/> 
    <xsl:element name="{$tag}"> 
    <xsl:value-of select="normalize-space(substring-after(.,':'))"/> 
    </xsl:element> 
</xsl:template> 

Таким образом, вы имеете возможность легко добавлять атрибуты для вывода элементов XML, если вам нужно, и не будет беспокоить с Disable-выход-отводящей и т.д.

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