XSLT - 如何仅保留XML中所需的元素

时间:2011-04-26 12:05:50

标签: xml xslt xpath

我有许多包含大量开销的XML文件。我希望只保留大约20个特定元素,并过滤掉其他任何内容。我知道我想要保留的所有元素的名字,我也知道它们是否是儿童元素,谁是他们的父母。我希望在转换后保留的这些元素仍然需要原始的层次结构放置。

E.g。我只想保持

  

<ns:currency>

<ns:stuff>
 <ns:things>
  <ns:currency>somecurrency</ns:currency>
  <ns:currency_code/>
  <ns:currency_code2/>
  <ns:currency_code3/>
  <ns:currency_code4/>
 </ns:things>
</ns:stuff>

让它看起来像这样;

<ns:stuff>
 <ns:things>
  <ns:currency>somecurrency</ns:currency>
 </ns:things>
</ns:stuff>

构建XSLT以实现此目的的最佳方法是什么?

2 个答案:

答案 0 :(得分:14)

这种一般转型

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

 <ns:WhiteList>
  <name>ns:currency</name>
  <name>ns:currency_code3</name>
 </ns:WhiteList>

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

 <xsl:template match=
  "*[not(descendant-or-self::*[name()=document('')/*/ns:WhiteList/*])]"/>
</xsl:stylesheet>

应用于提供的XML文档(添加了命名空间定义以使其格式正确):

<ns:stuff xmlns:ns="some:ns">
    <ns:things>
        <ns:currency>somecurrency</ns:currency>
        <ns:currency_code/>
        <ns:currency_code2/>
        <ns:currency_code3/>
        <ns:currency_code4/>
    </ns:things>
</ns:stuff>

产生想要的结果(白名单元素及其结构关系被保留):

<ns:stuff xmlns:ns="some:ns">
   <ns:things>
      <ns:currency>somecurrency</ns:currency>
      <ns:currency_code3/>
   </ns:things>
</ns:stuff>

<强>解释

  1. 标识规则/模板“按原样”复制所有节点。

  2. 样式表包含一个顶级<ns:WhiteList>元素,其<name>个子元素指定所有列入白名单的元素的名称 - 要在文档中保留其结构关系的元素。

  3. <ns:WhiteList>元素最好保存在单独的文档中,以便不需要使用新名称编辑当前样式表。为方便起见,白名单在同一样式表中。

  4. 一个模板会覆盖身份模板。它不会处理(删除)任何未列入白名单且没有白名单后代的元素。

答案 1 :(得分:6)

在XSLT中,您通常不会删除要删除的元素,但是要复制要保留的元素:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns="http://www.example.com/ns#"
    version="1.0">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>

     <xsl:template match="/ns:stuff">
        <xsl:copy>
            <xsl:apply-templates select="ns:things"/>
        </xsl:copy>
     </xsl:template>

     <xsl:template match="ns:things">
        <xsl:copy>
            <xsl:apply-templates select="ns:currency"/>
            <xsl:apply-templates select="ns:currency_code3"/>                   
        </xsl:copy>
     </xsl:template>

     <xsl:template match="ns:currency">
        <xsl:copy-of select="."/>
     </xsl:template>

     <xsl:template match="ns:currency_code3">
        <xsl:copy-of select="."/>
     </xsl:template>

</xsl:stylesheet>

上述示例仅复制currencycurrency_code3。输出如下:

<?xml version="1.0" encoding="UTF-8"?>
<ns:stuff xmlns:ns="http://www.example.com/ns#">
   <ns:things>
      <ns:currency>somecurrency</ns:currency>
      <ns:currency_code3/>
   </ns:things>
</ns:stuff>

注意:我为前缀ns添加了名称空间声明。

如果您要复制除少数元素之外的所有内容,您可能会看到此answer