xsl将path元素转换为元素树

时间:2015-06-05 13:42:31

标签: xslt tree muenchian-grouping

如果有人给我提示如何创建xslt,我会很高兴。可能是muenchian灌浆可以吗?是否可以为无限路径创建代码或者我必须限制路径元素的数量?非常感谢: - )

    <DETAILS>
       <DETAIL>
          <PATH>A\B\C\D</PATH>
          <VALUE>Value1<VALUE>
       <DETAIL>
       <DETAIL>
          <PATH>A\B\C\E</PATH>
          <VALUE>Value2<VALUE>
       <DETAIL>
       <DETAIL>
          <PATH>A\B\C\F</PATH>
          <VALUE>Value3<VALUE>
       <DETAIL>
       <DETAIL>
          <PATH>A\C\F</PATH>
          <VALUE>Value4<VALUE>
       <DETAIL>
       <DETAIL>
          <PATH>A\C\G</PATH>
          <VALUE>Value5<VALUE>
       <DETAIL>
    <DETAILS>

==&GT;转换为

    <A>
      <B>
        <C> 
          <D>Value1</D>
          <E>Value2</E>
          <F>Value3</F>
        </C>
      </B>
      <C> 
          <F>Value4</F>
          <G>Value5</G>
      </C>
     </A>

1 个答案:

答案 0 :(得分:0)

正如我在评论中所说,这并不简单,尤其是。如果仅限于XSLT 1.0。我的建议是分几步完成。第一步是将输入转换为以下内容:

<elems>
  <elem level="1" parent="">A</elem>
  <elem level="2" parent="A">B</elem>
  <elem level="3" parent="B">C</elem>
  <elem level="4" parent="C" value="Value1">D</elem>
  <elem level="1" parent="">A</elem>
  <elem level="2" parent="A">B</elem>
  <elem level="3" parent="B">C</elem>
  <elem level="4" parent="C" value="Value2">E</elem>
  <elem level="1" parent="">A</elem>
  <elem level="2" parent="A">B</elem>
  <elem level="3" parent="B">C</elem>
  <elem level="4" parent="C" value="Value3">F</elem>
  <elem level="1" parent="">A</elem>
  <elem level="2" parent="A">C</elem>
  <elem level="3" parent="C" value="Value4">F</elem>
  <elem level="1" parent="">A</elem>
  <elem level="2" parent="A">C</elem>
  <elem level="3" parent="C" value="Value5">G</elem>
</elems>

在第二步中,为第一级的每个不同elem创建一个元素。

最后,您递归地将模板应用于每个元素的不同子元素 - 即比当前级别深一级且其父级名称与当前元素名称匹配的元素。

以下样式表使用EXSLT扩展函数来标记路径并仅选择不同的节点。如果您的XSLT处理器不支持这些功能,则必须使用命名递归模板进行标记化,并使用Muenchian分组来选择不同的节点。

XSLT 1.0(+ EXSLT)

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:set="http://exslt.org/sets"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="exsl set str">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="children" match="elem" use="concat(@parent, '|', @level)" />

<xsl:variable name="elems">
    <xsl:for-each select="/DETAILS/DETAIL">
        <xsl:variable name="value" select="VALUE" />
        <xsl:for-each select="str:tokenize(PATH, '\')">
            <elem level="{position()}" parent="{preceding-sibling::token[1]}">
                <xsl:if test="position()=last()">
                    <xsl:attribute name="value">
                        <xsl:value-of select="$value"/>
                    </xsl:attribute>
                </xsl:if>
                <xsl:value-of select="."/>
            </elem>
        </xsl:for-each>
    </xsl:for-each>
</xsl:variable>

<xsl:variable name="elems-set" select="exsl:node-set($elems)" />

<xsl:template match="/">
    <output>
        <xsl:apply-templates select="set:distinct($elems-set/elem[@level=1])"/>
    </output>
</xsl:template>     

<xsl:template match="elem">
    <xsl:element name="{.}">
        <xsl:value-of select="@value"/>
        <xsl:apply-templates select="set:distinct(key('children', concat(., '|', @level + 1)))"/>
    </xsl:element>
</xsl:template> 

</xsl:stylesheet>

请注意,这一切都基于可能没有同名兄弟元素的假设。