xml - xslt - преобразовать выбранный элемент в атрибут

Я пытаюсь преобразовать документ XML в новый, в котором единственный из элементов преобразуется в атрибут и сохраняет остальную часть дерева документа таким же образом... Вот документ XML

    <?xml version="1.0" encoding="UTF-8"?>
    <cities>
    <city>
        <cityID>c1</cityID>
        <cityName>Atlanta</cityName>
        <cityCountry>USA</cityCountry>
        <cityPop>4000000</cityPop>
        <cityHostYr>1996</cityHostYr>   

    </city>

    <city>
        <cityID>c2</cityID>
        <cityName>Sydney</cityName>
        <cityCountry>Australia</cityCountry>
        <cityPop>4000000</cityPop>
        <cityHostYr>2000</cityHostYr>   
        <cityPreviousHost>c1</cityPreviousHost >   
    </city>

    <city>
        <cityID>c3</cityID>
        <cityName>Athens</cityName>
        <cityCountry>Greece</cityCountry>
        <cityPop>3500000</cityPop>
        <cityHostYr>2004</cityHostYr>   
        <cityPreviousHost>c2</cityPreviousHost >   
    </city>

    </cities>

Я пытаюсь получить элемент «cityID» в атрибут «город» и сохранить все остальное. Вот мой .xsl на данный момент. К сожалению, кажется, что он теряет остальные элементы:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

    <xsl:template match="/">
        <cities>
            <xsl:apply-templates/>
        </cities>
    </xsl:template>


    <xsl:template match="city">
        <xsl:element name="city" use-attribute-sets="NameAttributes"/>
    </xsl:template>


    <xsl:attribute-set name="NameAttributes">
        <xsl:attribute name="cityID">
            <xsl:value-of select="cityID"/>
        </xsl:attribute>
    </xsl:attribute-set>

    <xsl:template match="/ | @* | node()">
         <xsl:copy>
             <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>


</xsl:stylesheet>

person Ivan M    schedule 03.01.2016    source источник


Ответы (3)


я хотел бы использовать

<xsl:template match="city">
    <city cityID="{cityID}">
       <xsl:apply-templates select="node() except cityID"/> <!-- except is XSLT 2.0, use select="node()[not(self::cityID)]" for XSLT 1.0 -->
    </city>
</xsl:template>

или напишите шаблон для

<xsl:template match="cityID">
  <xsl:attribute name="{name()}" select="."/>
  <!-- XSLT 1.0 <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute> -->
</xsl:template>

Все атрибуты должны быть созданы перед дочерними узлами, поэтому для работы такого подхода может потребоваться использование <xsl:strip-space elements="*"/>.

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

person Martin Honnen    schedule 03.01.2016
comment
Этот ответ элегантен, но требует XSLT 2. Похоже, что исходный постер использует XSLT 1. - person Elliotte Rusty Harold; 03.01.2016
comment
В ответе упоминаются альтернативы XSLT 1.0 для этих конструкций XSLT/XPath 2.0. - person Martin Honnen; 03.01.2016
comment
Спасибо, Мартин, отличный ответ - на самом деле я использую 1.0, но вы также дали мне правильное решение .... 10x Bro - person Ivan M; 03.01.2016

Шаблон, соответствующий элементу города, не обрабатывает дочерние элементы этого элемента. Замените его следующим:

<xsl:template match="city">
    <xsl:element name="city" use-attribute-sets="NameAttributes">
      <xsl:apply-templates select="node()[name()!='cityID']" />
    </xsl:element>
</xsl:template>
person Elliotte Rusty Harold    schedule 03.01.2016
comment
спасибо, Гарольд, это сделал :) отлично и, главное, просто, без особых изменений в коде - person Ivan M; 03.01.2016

Простое преобразование (полный XSLT 1.0):

<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="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="city">
    <city cityID="{cityID}">
      <xsl:apply-templates select="@*|node()"/>
    </city>
  </xsl:template>
  <xsl:template match="cityID"/>
</xsl:stylesheet>
person Dimitre Novatchev    schedule 03.01.2016