加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

xml – xslt 1.0合并空元素名称

发布时间:2020-12-16 22:52:54 所属栏目:百科 来源:网络整理
导读:关于使用xslt 1.0的一个快速问题,你可以帮助我.我有一个输入xml,如下所示 Root FirstNameBob/FirstName LastNameMarley/LastName IDBM1234/ID Songs Song EmptyElements/EmptyElements SongNameNo woman no cry/SongName Year1974/Year album/album studio/s
关于使用xslt 1.0的一个快速问题,你可以帮助我.我有一个输入xml,如下所示

<Root>
    <FirstName>Bob</FirstName>
    <LastName>Marley</LastName>
    <ID>BM1234</ID>
    <Songs>
        <Song>
            <EmptyElements></EmptyElements>
            <SongName>No woman no cry</SongName>
            <Year>1974</Year>
            <album></album>
            <studio></studio>
            <rating></rating>
        </Song>
    </Songs>
</Root>

输出需要看起来像

<Root>
    <FirstName>Bob</FirstName>
    <LastName>Marley</LastName>
    <ID>BM1234</ID>
    <Songs>
        <Song>
            <EmptyElements>album,studio,rating</EmptyElements>
            <SongName>No woman no cry</SongName>
            <Year>1974</Year>
        </Song>
    </Songs>
</Root>

所以基本上将所有空元素的逗号分隔列表放入EmptyElements标记中.

解决方法

这种转变:

<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="EmptyElements" priority="5">
    <xsl:copy>
      <xsl:apply-templates mode="enumerate" select=
      "../*[not(self::EmptyElements) and not(node())]" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Songs/Song/*" mode="enumerate">
    <xsl:value-of select="substring(',',not(position() = 1),1)"/>
    <xsl:value-of select="name()"/>
  </xsl:template>
  <xsl:template match="Songs/Song/*[not(node())]"/>
</xsl:stylesheet>

应用于提供的源XML文档时:

<Root>
    <FirstName>Bob</FirstName>
    <LastName>Marley</LastName>
    <ID>BM1234</ID>
    <Songs>
        <Song>
            <EmptyElements></EmptyElements>
            <SongName>No woman no cry</SongName>
            <Year>1974</Year>
            <album></album>
            <studio></studio>
            <rating></rating>
        </Song>
    </Songs>
</Root>

产生想要的,正确的结果:

<Root>
   <FirstName>Bob</FirstName>
   <LastName>Marley</LastName>
   <ID>BM1234</ID>
   <Songs>
      <Song>
         <EmptyElements>album,rating</EmptyElements>
         <SongName>No woman no cry</SongName>
         <Year>1974</Year>
      </Song>
   </Songs>
</Root>

说明:

>选择执行时,标识规则将“按原样”复制匹配的节点
>匹配Songs / Song / * [not(node())]的模板,当选择执行时,不执行任何操作,这会导致“删除”(不复制)输出中的匹配节点.
>匹配EmptyElements的模板具有比上述“删除”模板更高的优先级,因此选择在任何EmptyElements元素上执行.
>将匹配的EmptyElements元素浅层复制到输出,然后通过将模板枚举模板应用于所有空的siblings-elements来生成其内容(正文).
>最后,模式枚举中的模板匹配Song元素的任何子元素,该元素是Songs元素的子元素.它由< xsl:apply-templates>选择执行.上面步骤4中的指令,仅适用于EmptyElements元素的空元素兄弟节点.此模板执行两项操作:a)输出逗号,如果这不是node-list中的第一个节点; b)输出匹配元素的名称.这样,输出EmptyElements元素的空兄弟元素的所有名称,用逗号分隔.

更新:

亲爱的读者,
我们有一个同伴的答案,这个问题以或简单地开头:
并且暗示它比这个答案中的代码更简单.

而不是告诉你这个答案比简单地简单:-answer,我总结了一些与简单相关的事实,你可以自己做出结论.在下表中,每个左子列中的值都是针对此的当前解决方案.每个右侧子列中的值仅适用于Or:-solution:

除此之外,简单地说: – 解决方案也具有潜在的性能和一定的可流动性问题 – 请参阅此片段:

<xsl:if test="position()!=last()">
                <xsl:text>,</xsl:text>
             </xsl:if>

与当前解决方案使用的内容相比:

not(position() = 1)

见Dr. Michael Kay’s recommendation,后者是“比这更好的编码方式”,他解释了为什么:

“Why? Because however hard the optimizer works,the last() function is hard
work: it involves some kind of lookahead. With “position() ne last()” the
lookahead might be limited to one element,but it’s still a lot more
complicated than testing whether the position is 1.

With streaming coming along,the latter formulation is also more likely to
be streamable (because lookahead is impossible with streaming).”

结论:每当有人告诉我们:“或者简单地说:”,在将他们的陈述视为理所当然之前采取一些指标是很好的…

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读