分析XML的树/结构(引用彼此的标签)

时间:2012-08-13 12:41:29

标签: xml xslt reference refer

我使用“父”子元素获得了几个XML -elements。并非所有toplevel -elements都需要复制,因此我有一个固定的(main-)section uniqueNames列表,需要复制。

应在我的XSL中复制哪些小节的主要部分列表:

<xsl:variable name="mainSections">|news|sport|</xsl:variable>

源XML主要部分:

<section uniqueName="news">
</section>

<section uniqueName="sport">
</section>

<section uniqueName="travel">
</section>

源XML子部分:

<section uniqueName="national_news">
  <parent uniqueName="news"/>
</section>

<section uniqueName="regional_news">
  <parent uniqueName="national_news"/>
</section>

<section uniqueName="city_news">
  <parent uniqueName="regional_news"/>
</section>

<section uniqueName="travel_europe">
  <parent uniqueName="travel"/>
</section>

<section uniqueName="holland">
  <parent uniqueName="travel_europe"/>
</section>

因为子部分很容易在开发阶段和生成我的XSL之间移动,更改或删除,所以我需要动态确定任何给定的子部分是否是其中一个主要部分的子部分。总共还有无数的小节。硬编码要复制的子部分列表是可撤消的。

分段深度可以非常深,如示例所示:“city_news”部分将“regional_news”作为父级,其中“national_news”为父级,其中“news”为父级,因此本节需要复制,因为它最终是“新闻”的孩子。 “holland”部分(在“travel_europe”小节下)的顶级部分“Travel”不在要复制的列表中,因此需要忽略。

一开始我尝试检查每个元素,如果父元素在列表中,但那只是愚蠢的,它只能让我达到1级深度。 我的最后一次尝试是创建一个javascript,首先索引所有部分,然后分析结构,消除与列表中不包含的mainsections相关的所有部分。 但是调用脚本也证明是一个挑战,因为XSL没有办法调用javascript。

我对如何继续这个有点无能为力......任何解决方案或建议?

源XML文档是3500行,其中的信息对此问题无关紧要。问题是如何过滤掉一个主要部分的子部分的子部分,或者:如何确定一个子部分是否是树的几步之后指定主要部分的子部分。 考虑要输入的5个子部分,然后输出应为:

<section uniqueName="national_news">
  <parent uniqueName="news"/>
</section>

<section uniqueName="regional_news">
  <parent uniqueName="national_news"/>
</section>

<section uniqueName="city_news">
  <parent uniqueName="regional_news"/>
</section>

<section uniqueName="travel_europe">
  <parent uniqueName="travel"/>
</section>

<section uniqueName="holland">
  <parent uniqueName="travel_europe"/>
</section>

涉及“旅行”主要部分,该部分不在要复制的列表中。

1 个答案:

答案 0 :(得分:0)

此转化

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:param name="pWanted" select="'|news|sport|'"/>

 <xsl:key name="kChildren" match="section" use="parent/@uniqueName"/>

 <xsl:template match="/*">
     <xsl:call-template name="getSections">
       <xsl:with-param name="pParents" select=
       "section[contains($pWanted, concat('|',@uniqueName, '|'))]"/>
     </xsl:call-template>
 </xsl:template>

 <xsl:template name="getSections">
  <xsl:param name="pParents" select="/.."/>

  <xsl:if test="$pParents">
    <xsl:copy-of select="$pParents"/>
    <xsl:call-template name="getSections">
     <xsl:with-param name="pParents"
        select="key('kChildren', $pParents/@uniqueName)"/>
    </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于以下XML文档(没有提供!!!):

<t>
    <section uniqueName="news"></section>
    <section uniqueName="sport"></section>
    <section uniqueName="travel"></section>
    <section uniqueName="national_news">
        <parent uniqueName="news"/>
    </section>
    <section uniqueName="regional_news">
        <parent uniqueName="national_news"/>
    </section>
    <section uniqueName="city_news">
        <parent uniqueName="regional_news"/>
    </section>
    <section uniqueName="travel_europe">
        <parent uniqueName="travel"/>
    </section>
    <section uniqueName="holland">
        <parent uniqueName="travel_europe"/>
    </section>
</t>

产生想要的(在问题中未完全指定!!!),结果正确

<section uniqueName="news"/>
<section uniqueName="sport"/>
<section uniqueName="national_news">
   <parent uniqueName="news"/>
</section>
<section uniqueName="regional_news">
   <parent uniqueName="national_news"/>
</section>
<section uniqueName="city_news">
   <parent uniqueName="regional_news"/>
</section>

<强>解释

正确使用 keys 和递归。