如何在XSLT中编写一个保留所选节点的子节点的标识转换?

时间:2011-02-04 13:00:56

标签: xml xslt

我刚刚开始使用XSLT,并且熟悉身份模板,这在很大程度上要归功于Dimitre Novatchev,,他已就该主题提供了一些很好的答案。

我正在执行XML到XML的转换,试图仅隔离和复制大型模式文件的几个元素。这是一个非常简化的数据版本:

XSD来源

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" version="1.0">

<xsd:simpleType name="Alpha">
    <xsd:restriction base="xsd:decimal">
        <xsd:fractionDigits value="1"/>
        <xsd:minInclusive value="0.0"/>
        <xsd:maxInclusive value="100.0"/>
    </xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="Bravo">
    <xsd:annotation>
        <xsd:documentation>
            Bravo data type.
        </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:integer"/>
</xsd:simpleType>

<xsd:simpleType name="Charlie">
    <xsd:annotation>
        <xsd:documentation>
        Charlie data type.
        </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:integer"/>
</xsd:simpleType>

<xsd:simpleType name="Delta">
    <xsd:annotation>
        <xsd:documentation>
        Delta data type.
        </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:integer"/>
</xsd:simpleType>
</xsd:schema>

XSLT样式表

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes" />   
<!-- identity template -->
<xsl:template match="/ | node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*/node()[ 
                               not ( @name='Alpha')
                               and  
                               not ( @name='Charlie')
                                ]

                               "/>
</xsl:stylesheet>

结果

<?xml version="1.0"?>
<xsd:schema attributeFormDefault="unqualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:simpleType name="Alpha"></xsd:simpleType>
<xsd:simpleType name="Charlie"></xsd:simpleType>
</xsd:schema>

这非常接近,但我需要结果中所选节点Alpha和Charlie的子节点,就像我执行了copy-of一样。

我需要什么

<?xml version="1.0"?>
<xsd:schema attributeFormDefault="unqualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:simpleType name="Alpha">
        <xsd:restriction base="xsd:decimal">
        <xsd:fractionDigits value="1"/>
        <xsd:minInclusive value="0.0"/>
        <xsd:maxInclusive value="100.0"/>
    </xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="Charlie">
    <xsd:annotation>
        <xsd:documentation>
            Charlie data type.
        </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:integer"/>
</xsd:simpleType>
</xsd:schema>

有没有办法选择copy-of,的元素,或者在我的match子句中指定我想要递归到Alpha和Charlie的孩子身上?

谢谢!

2 个答案:

答案 0 :(得分:2)

您需要将逻辑转换为复制除“Bravo”和“Delta”元素之外的所有内容。

空模板如下所示:

<xsl:template match="xs:simpleType[@name[.='Bravo' or .='Delta']]"
              xmlns:xs="http://www.w3.org/2001/XMLSchema"/> 

注意:添加命名空间,以防万一...

另一种方式,更多语义:

<xsl:template match="/*/*[not(@name[.='Alpha' or .='Charlie'])]"/> 

答案 1 :(得分:2)

或者,除了@Alejandro的好答案,您可以解决代码中的问题

只需更改

<xsl:template match=
 "*/node()[
           not ( @name='Alpha')
          and
           not ( @name='Charlie')
           ]
  "/>

<xsl:template match=
 "/*/node()[
           not ( @name='Alpha')
          and
           not ( @name='Charlie')
           ]
  "/>

解释:最初提供的“删除模板”匹配的节点太多。它必须只匹配顶部元素的子元素。