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

xml – XSLT – 在分隔符上爆炸节点

发布时间:2020-12-16 22:50:02 所属栏目:百科 来源:网络整理
导读:我需要一个XSLT 1.0来分解分隔符上的 XML节点并创建单个节点. 例如,如果分隔符为“_”且XML为: root a_b_chelloa_b_c a_b_c1world/a_b_c1/root 结果XML应该是: root a b chello/c c1world/c1 /b /a/root 不包含分隔符的节点应按原样输出. 我真的需要在XSLT
我需要一个XSLT 1.0来分解分隔符上的 XML节点并创建单个节点.
例如,如果分隔符为“_”且XML为:

<root>
    <a_b_c>hello<a_b_c>
    <a_b_c1>world</a_b_c1>
</root>

结果XML应该是:

<root>
    <a>
        <b>
            <c>hello</c>
            <c1>world</c1>
        </b>
    </a>
</root>

不包含分隔符的节点应按原样输出.
我真的需要在XSLT1.0中使用它
谢谢您的帮助.

解决方法

这种转变:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

  <xsl:key name="kSameNameAdj" match="*"
  use="concat(generate-id(..),'+',generate-id(preceding-sibling::*[not(name()=name(current()))][1])
              )"/>

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

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <xsl:apply-templates select="node()"/>
  </xsl:variable>

  <xsl:apply-templates select="ext:node-set($vrtfPass1)" mode="compress"/>
 </xsl:template>

 <xsl:template name="explode" match=
  "*[contains(name(),'_')
   and not(substring(name(),1,1)='_')
   and not(substring(name(),string-length(name()))='_')
    ]">
    <xsl:param name="pName" select="name()"/>
    <xsl:param name="pText" select="text()"/>

  <xsl:choose>
   <xsl:when test="not($pName)">
    <xsl:value-of select="$pText"/>
   </xsl:when>
   <xsl:otherwise>
      <xsl:element name="{substring-before(concat($pName,'_'),'_')}">
       <xsl:call-template name="explode">
         <xsl:with-param name="pName" select="substring-after($pName,'_')"/>
         <xsl:with-param name="pText" select="$pText"/>
       </xsl:call-template>
      </xsl:element>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

  <xsl:template match="/" name="fold" mode="compress">
  <xsl:param name="pDoc" select="/"/>

  <xsl:choose>
    <xsl:when test="not($pDoc//*[name()=name(following-sibling::*[1])])">
      <xsl:copy-of select="$pDoc"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="vrtfThisPass">
        <xsl:apply-templates select="$pDoc/*" mode="compress"/>
      </xsl:variable>

      <xsl:call-template name="fold">
        <xsl:with-param name="pDoc" select="ext:node-set($vrtfThisPass)"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="node()|@*" mode="compress">
   <xsl:copy>
     <xsl:apply-templates select="@*|node()[1]" mode="compress"/>
   </xsl:copy>
   <xsl:apply-templates select="following-sibling::node()[1]" mode="compress"/>
 </xsl:template>

 <xsl:template match="*[name()=name(following-sibling::*[1])]" mode="compress">
  <xsl:element name="{name()}">
    <xsl:apply-templates mode="compress" select=
    "key('kSameNameAdj',concat(generate-id(..),generate-id(preceding-sibling::*)
                 )
         )/node()"/>
  </xsl:element>
  <xsl:apply-templates mode="compress" select=
  "key('kSameNameAdj',generate-id(preceding-sibling::*)
                 )
         )
          [last()]/following-sibling::node()[1]
   "/>
 </xsl:template>
</xsl:stylesheet>

当应用于以下XML文档时(提供的文档,扩展为更具挑战性):

<root>
   <x>This is:</x>
     <a_b_c>hello</a_b_c>
     <a_b_c_d>my</a_b_c_d>
     <a_b_c1>wonderful</a_b_c1>
     <a_b_c>world</a_b_c>
     <a_b>!</a_b>
   <y>The End</y>
</root>

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

<root>
   <x>This is:</x>
   <a>
      <b>
         <c>hello<d>my</d>
         </c>
         <c1>wonderful</c1>
         <c>world</c>!</b>
   </a>
   <y>The End</y>
</root>

说明:

0.1.这是一个多次转换.
第一遍将XML文档转换为:

<root>
   <x>This is:</x>
   <a>
      <b>
         <c>hello</c>
      </b>
   </a>
   <a>
      <b>
         <c>
            <d>my</d>
         </c>
      </b>
   </a>
   <a>
      <b>
         <c1>wonderful</c1>
      </b>
   </a>
   <a>
      <b>
         <c>world</c>
      </b>
   </a>
   <a>
      <b>!</b>
   </a>
   <y>The End</y>
</root>

0.2.随后的传递,每个都将具有相同名称的任何相邻元素组压缩到具有该名称的单个元素中 – 然后递归地处理结果,直到不再存在具有相同名称的多于一个相邻兄弟元素的任何组.

0.3.第一遍使用identity rule.

0.4.下一次传递在“压缩”模式下使用fine-grade identity模板.

(编辑:李大同)

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

    推荐文章
      热点阅读