2

我有一个具有大致以下结构的 XML,这里的相关特征是元素对“F”和“Child_Fs”的递归关系。“Child_Fs”可以包含任意数量的“F”,而“F”只能包含一个“Child_Fs”:

<A>
    <B>
        <F id="1">
            <J/>
            <K/>
            <Child_Fs>
                <F id="1.1">
                    <J/>
                    <K/>
                    <Child_Fs>
                        <F id="1.1.1">
                            <J/>
                            <K/>
                            <Child_Fs>
                                    ...
                            </Child_Fs>
                        </F>
                        <F id="1.1.2">
                            ...
                        </F>
                        <F id="1.1.3">
                            ...
                        </F>
                        <F id="1.1.4">
                            ...
                        </F>
                        .
                        .
                        .
                    </Child_Fs>
                </F>
                <F id="1.2">
                    ...
                </F>
                <F id="1.3">
                    ...
                </F>
                <F id="1.4">
                    ...
                </F>
                .
                .
                .
            </Child_Fs>
        </F>
        <F id="2">
            ...
        </F>
        <F id="3">
            ...
        </F>
        <F id="4">
            ...
        </F>
        .
        .
        .
        <G/>
        <H/>
        <I/>
    </B>
    <C/>
    <D/>
    <E/>
</A>

我的实际 XML 不包含 ID,我只是在此示例中编写它们以用于说明目的。

所以我想在转换后得到以下 XML,其中所有“F”元素都是其对应的最高“F/Child_Fs”祖先的子元素。这意味着 F 元素的最大深度应仅出现两次 (F/Child_Fs/F/Childfs)。这里的另一个重要要求是保持所有数据(包括属性和文本)完好无损,这只是一个重定位操作:

<A>
    <B>
        <F id="1">
            <J/>
            <K/>
            <Child_Fs>
                <F id="1.1">
                    <J/>
                    <K/>
                    <Child_Fs>
                    </Child_Fs>
                </F>
                <F id="1.1.1">
                    <J/>
                    <K/>
                    <Child_Fs>
                    </Child_Fs>
                </F>
                ...
                <F id="1.1.2">
                    ...
                </F>
                <F id="1.1.3">
                    ...
                </F>
                <F id="1.1.4">
                    ...
                </F>
                .
                .
                .
                <F id="1.2">
                    ...
                </F>
                <F id="1.3">
                    ...
                </F>
                <F id="1.4">
                    ...
                </F>
                .
                .
                .
            </Child_Fs>
        </F>
        <F id="2">
            ...
        </F>
        <F id="3">
            ...
        </F>
        <F id="4">
            ...
        </F>
        .
        .
        .
        <G/>
        <H/>
        <I/>
    </B>
    <C/>
    <D/>
    <E/>
</A>

如果有人能给我一个提示,我将不胜感激。直到现在我还没有想出一个正确的 XSL 样式表。

提前谢谢了。

4

2 回答 2

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="Child_Fs[ancestor::Child_Fs]">
   <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<A>
    <B>
        <F id="1">
            <J/>
            <K/>
            <Child_Fs>
                <F id="1.1">
                    <J/>
                    <K/>
                    <Child_Fs>
                        <F id="1.1.1">
                            <J/>
                            <K/>
                            <Child_Fs>
                                    ...
                            </Child_Fs>
                        </F>
                        <F id="1.1.2">
                            ...
                        </F>
                        <F id="1.1.3">
                            ...
                        </F>
                        <F id="1.1.4">
                            ...
                        </F>
                        .
                        .
                        .
                    </Child_Fs>
                </F>
                <F id="1.2">
                    ...
                </F>
                <F id="1.3">
                    ...
                </F>
                <F id="1.4">
                    ...
                </F>
                .
                .
                .
            </Child_Fs>
        </F>
        <F id="2">
            ...
        </F>
        <F id="3">
            ...
        </F>
        <F id="4">
            ...
        </F>
        .
        .
        .
        <G/>
        <H/>
        <I/>
    </B>
    <C/>
    <D/>
    <E/>
</A>

产生想要的正确结果:

<A>
   <B>
      <F id="1">
         <J/>
         <K/>
         <Child_Fs>
            <F id="1.1">
               <J/>
               <K/>
               <F id="1.1.1">
                  <J/>
                  <K/>
                                        ...
                                </F>
               <F id="1.1.2">
                                ...
                            </F>
               <F id="1.1.3">
                                ...
                            </F>
               <F id="1.1.4">
                                ...
                            </F>
                            .
                            .
                            .
                        </F>
            <F id="1.2">
                        ...
                    </F>
            <F id="1.3">
                        ...
                    </F>
            <F id="1.4">
                        ...
                    </F>
                    .
                    .
                    .
                </Child_Fs>
      </F>
      <F id="2">
                ...
            </F>
      <F id="3">
                ...
            </F>
      <F id="4">
                ...
            </F>
            .
            .
            .
            <G/>
      <H/>
      <I/>
   </B>
   <C/>
   <D/>
   <E/>
</A>

说明

正确使用和覆盖身份规则

于 2012-07-17T01:24:40.157 回答
0

只要您描述的结构保持到位,您就可以使用如下所述的相当简单的算法。如果结构变得更加自由形式,那么它就会成为一个更难的问题。

算法

Child_Fs 正好有 1 个祖先 F:

  • 这些是收件人。他们将拉入所有后代 F

具有超过 1 个祖先 F 的 Child_Fs:

  • 这些是捐助者。复制其他孩子但排除 F 孩子

d

<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xi="http://www.w3.org/2001/XInclude"
      exclude-result-prefixes="xsl xi">
 <xsl:output method="xml" indent="yes"/>
 <xsl:strip-space elements="*" />
 
 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Child_Fs[count(ancestor::F)=1]">
 <!-- Child_F which is recipient of all Fs. -->
 <xsl:copy>
  <xsl:apply-templates select="@* | node() | //F" />
 </xsl:copy>
</xsl:template> 

<xsl:template match="Child_Fs[count(ancestor::F) &gt; 1]">
 <!-- Child_F which is donor of Fs. -->
 <xsl:copy>
  <xsl:apply-templates select="@* | node()[not(self::F)]" />
 </xsl:copy>
</xsl:template>

</xsl:stylesheet> 
于 2012-07-17T01:35:20.410 回答