开发者

How do I write an identity transform in XSLT that preserves children of selected nodes?

I've just begun using XSLT, and am becoming familiar with the identity template, thanks in large part to Dimitre Novatchev, who has provided some great answers on the topic.

I am performing an XML-to-XML transform, trying to isolate and copy out only a few elements of a large schema file. Here is a much-simplified version of the data:

XSD Source

<?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 Stylesheet

<?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>
开发者_开发百科

The Results

<?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>

This is really close, but I need the children of selected nodes Alpha and Charlie in the results, as if I had performed a copy-of.

What I need

<?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>

Is there a way to select the elements with copy-of, or to specify in my match clause that I want to recurse into the children of Alpha and Charlie?

Thanks!


You need to reverse your logic into copy all except for "Bravo" and "Delta" elements.

The empty template will look like:

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

Note: Adding the namespace, just in case...

Another way, more semantic:

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


Or, alternatively to the good answer by @Alejandro, you can fix the issues in your code:

Just change:

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

to:

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

Explanation: The originally provided "deletion template" is matching too-many nodes. It must only match children-elements of the top element.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜