【问题标题】:xml - xslt - transform a chosen element into attributexml - xslt - 将所选元素转换为属性
【发布时间】:2016-01-03 14:55:24
【问题描述】:

我正在尝试将 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”元素转换为“city”的属性并保留其余部分。到目前为止,这是我的 .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>

【问题讨论】:

    标签: xml xslt transform stylesheet elements


    【解决方案1】:

    我会用

    <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>
    

    所有属性都需要在子节点之前创建,因此使用&lt;xsl:strip-space elements="*"/&gt; 可能是该方法起作用的必要条件。

    这两个建议都假定存在身份转换模板,而您已经拥有了。

    【讨论】:

    • 这个答案很优雅,但需要 XSLT 2。看起来原始发布者使用的是 XSLT 1。
    • 答案提到了那些 XSLT/XPath 2.0 构造的 XSLT 1.0 替代方案。
    • 谢谢马丁,很好的回答 - 实际上我使用的是 1.0 但你也给了我正确的解决方案.... 10x Bro
    【解决方案2】:

    匹配城市元素的模板不处理该元素的子元素。将其替换为以下内容:

    <xsl:template match="city">
        <xsl:element name="city" use-attribute-sets="NameAttributes">
          <xsl:apply-templates select="node()[name()!='cityID']" />
        </xsl:element>
    </xsl:template>
    

    【讨论】:

    • 感谢 Harold,他做到了 :) 很棒,最重要的是简单,代码没有太多改动
    【解决方案3】:

    就这么简单(完整的 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-13
      • 2018-09-22
      • 1970-01-01
      • 2012-05-30
      • 1970-01-01
      • 2013-06-18
      • 1970-01-01
      • 2017-06-17
      相关资源
      最近更新 更多