I have this xml:
<?xml version="1.0" encoding="utf-8"?>
<xml>
<head>
<name>This is my XML</name>
<version>This is my XML</version>
</head>
<body>
<item id="SH2-99435">
<properties>
<property id="69">
<name>This is a property</name>
<amount>54.13</amount>
<estructure id="IZ4">
<name>caterpillar</name>
<location><zipCode>02210</zipCode><street>South Station</street></location>
</estructure>
</property>
<features id="ABC3">
<feature>If it works, a bug is another feature.</feature>
<feature>feature!!</feature>
</features>
</properties>
<coding>
<codename>Silent Hill 2</codename>
<developer>Team Silent</developer>
<publisher>Konami</publisher>
</coding>
</item>
<item id="SH3-4498">
<text value="it has values like the other item"/>
</item>
<item id="MGS-2">
<text value="it has values like the other item"/>
</item>
</body>
</xml>
And I want to achieve this:
<?xml version="1.0" encoding="utf-8"?>
<xml>
<head>
<name>This is my XML</name>
<version>This is my XML</version>
</head>
<body>
<item>
<properties>
<property id="69">
<amount>54.13</amount>
<estructure id="IZ4">
<name>caterpillar</name>
<location><zipCode>02210</zipCode><street>South Station</street></location>
</estructure>
</property>
</properties>
</item>
<item id="SH3-4498">
<text value="it should have properties and the selected sons"/>
</item>
<item id="MGS-2" >
<text value="it should have properties and the selected sons"/>
</item>
</body>
</xml>
I have something like this, which filters correctly:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xml/body/item/coding" />
<xsl:template match="xml/body/item/properties/features" />
<xsl:template match="xml/body/item/properties/property/name" />
</xsl:stylesheet>
I have been told that there are going to be 10 files being produced by running this filter, each one with different tags; but if a new tag comes, we would have to change 10 files to exclude the unwanted tag, instead of only add a tag on the file that is needed. For example, on the other file, only coding is going to be included, and so on.
I tried with this:
<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>amount</name>
<name>estructure</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>
But it doesn’t copy the children of estructure.
Do you know what I could do?
Thanks.
Update. Added justification to make it this way and not the other way around, and more descriptive question.
I wouldn’t accept this answer, but in answer to your immediate question, you are testing for elements which are ancestors (or self) of the estructure element, but you ignore anything else. This means descendants of the estructure are ignored. Change your xsl:if condition to the following
Yuck.
Honestly, your first XSLT is much nicer and cleaner.
It would probably help if you explained exactly what the rules are you are trying to follow with the transformation. If the rules are to copy everything except certain nodes, then your first XSLT is ideal for that. If the rules are copy only explicit nodes, then could you give a bit more detail as to what exactly needs to be copied, and it should be possible to rustle up something much nicer.
EDIT:
In response to the clarification, try this XSLT
I have tried to tidy it up a bit by using a variable to hold the document look-up. Note the reason for using the xsl:if is that you can’t use variables in the template match.