使用XSLT从XML模式中删除未使用的元素

时间:2011-04-13 04:57:48

标签: xslt recursion schema

我正在寻找一种方法(如果可能的话)使用XSD文档的XSL转换来删除未使用的元素。这在我的工作中出现了很多,公司将在其中定义一个绝对包含XSD的所有内容,但随后他们将需要为其中的单个根元素创建一个缩减版本。

为了进一步解释,我可能有如下的XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="RootElement">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="ChildElement"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="ChildElement"/>
    <xs:element name="UnusedElement"/>
</xs:schema>

我希望能够设置一个XSL,我提供了起始元素(在本例中为RootElement),它将复制所有依赖元素,但省略未使用的元素。在上面的示例中,如果我传入RootElement,我希望包含RootElementChildElement,但UnusedElement被省略。

(当我说“提供起始元素”时,我很高兴破解样式表并在必要时输入xsl:template match="RootElement"。)

这显然必须是递归的,因此会导航在起始元素下面定义的整个结构,并且该模式中未使用的任何元素都将被丢弃。

(当然,如果它可以在任何导入的模式中执行相同的操作会更好!)

我已经广泛搜索过谷歌并且找不到任何相关内容 - 我不确定这是否意味着它不可能。

谢谢!

修改:实际上我可能应该澄清并说我想要删除未使用的元素和类型,因此它会遵循ref="childElement"type="someType"链接。

1 个答案:

答案 0 :(得分:4)

此转化

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

 <xsl:param name="ptopElementName" select="'RootElement'"/>

 <xsl:variable name="vTop" select=
 "/*/xs:element[@name=$ptopElementName]"/>

 <xsl:variable name="vNames"
      select="$vTop/descendant-or-self::*/@name"/>

 <xsl:variable name="vRefs"
      select="$vTop/descendant-or-self::*/@ref"/>

 <xsl:variable name="vTypes"
      select="$vTop/descendant-or-self::*/@type"/>

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

 <xsl:template match="xs:element">
  <xsl:if test=
    "@name=$vNames
    or
     @name=$vRefs
    or
     ancestor-or-self::*[@name=$ptopElementName]">
   <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>

 <xsl:template match="xs:complexType|xs:simpleType">
  <xsl:if test=
   "@name=$vTypes
    or
     ancestor-or-self::*[@name=$ptopElementName]">
   <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="RootElement">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="ChildElement"/>
            </xs:sequence>
        </xs:complexType></xs:element>
    <xs:element name="ChildElement"/>
    <xs:element name="UnusedElement"/>
</xs:schema>

生成所需的核心结果:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
   <xs:element name="RootElement">
      <xs:complexType>
         <xs:sequence>
            <xs:element ref="ChildElement"/>
         </xs:sequence>
      </xs:complexType>
   </xs:element>
   <xs:element name="ChildElement"/>
</xs:schema>