-2

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

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

==> 转换为

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

1 回答 1

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>

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

于 2015-06-05T17:24:42.707 回答