Create an XSL stylesheet to omit unwanted elements based on input parameters

It will be a little long and specific, so please bear with me. I understand how XSLT works, but I do not know all the elements that perform operations. Any help you can provide will be appreciated.

Suppose I have a pilot manual for the 737s written in XML. However, there are 3 types of 737 (400, 600, and 800), and although 90% of the manual is the same for all three types, there are certain parts that are specific to each type. Some pilots only learn about 1 or 2 (or sometimes all 3) jets, so I would like to omit sections that do not matter to them. This is how I set up XML:

<manual> <section>A: This is relevant for every type</section> <section t600="no" t800="no">B: This is relevant only for the 737-400</section> <section t800="no">C: This is relevant for 737-400 and 737-600</section> <section t400="no">D: This is relevant for 737-600 and 737-800</section> </manual> 

I want to somehow indicate that I am only interested in, for example, 737-800 and get a manual like this:

 <manual> <section>A: This is relevant for every type</section> <section>D: This is relevant for 737-600 and 737-800</section> </manual> 

Or for another pilot who is interested in two jets, for example 737-400 and 737-600, the manual will look like this:

 <manual> <section>A: This is relevant for every type</section> <section>B: This is relevant only for the 737-400</section> <section>C: This is relevant for 737-400 and 737-600</section> <section>D: This is relevant for 737-600 and 737-800</section> </manual> 

I have access to the original XML, so if the way I configured it does not make sense, I can change it. I thought that almost everything is the same for all types it makes sense to refuse, but I understand that this can make it difficult to match? I'm not sure.

Thanks again for watching! Let me know if I left something.

+6
source share
1 answer

I. XSLT 2.0 Solution :

 <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:param name="pInterests"> <interest topic="t800"/> </xsl:param> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match= "section[some $t in $pInterests/*/@topic satisfies not($t = current()/@*[. eq 'no']/name()) ] "> <section><xsl:apply-templates/></section> </xsl:template> <xsl:template match="section"/> </xsl:stylesheet> 

when applied to the provided XML document :

 <manual> <section>A: This is relevant for every type</section> <section t600="no" t800="no">B: This is relevant only for the 737-400</section> <section t800="no">C: This is relevant for 737-400 and 737-600</section> <section t400="no">D: This is relevant for 737-600 and 737-800</section> </manual> 

creates the desired, correct result :

 <manual> <section>A: This is relevant for every type</section> <section>D: This is relevant for 737-600 and 737-800</section> </manual> 

If we replace the current parameter in the transformation :

  <xsl:param name="pInterests"> <interest topic="t800"/> </xsl:param> 

from

  <xsl:param name="pInterests"> <interest topic="t400"/> <interest topic="t600"/> </xsl:param> 

and again apply the modified transformation in the same XML document, we will also get the desired and correct result :

 <manual> <section>A: This is relevant for every type</section> <section>B: This is relevant only for the 737-400</section> <section>C: This is relevant for 737-400 and 737-600</section> <section>D: This is relevant for 737-600 and 737-800</section> </manual> 

II. XSLT 1.0 Solution :

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:param name="pInterests"> <interest topic="t800"/> </xsl:param> <xsl:key name="kSectionTypeAttrByName" match="section/@*" use="concat(generate-id(..),'|', name())"/> <xsl:variable name="vInterests" select= "document('')/*/xsl:param[@name='pInterests']/*"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="section"> <xsl:variable name="vSec" select="."/> <xsl:variable name="vHasInterest"> <xsl:for-each select="$vInterests/@topic"> <xsl:variable name="vTopic" select="."/> <xsl:for-each select= "$vSec[not(key('kSectionTypeAttrByName', concat(generate-id(),'|', $vTopic) ) = 'no' ) ]"> <xsl:text>1</xsl:text> </xsl:for-each> </xsl:for-each> </xsl:variable> <xsl:if test="string($vHasInterest)"> <section><xsl:apply-templates/></section> </xsl:if> </xsl:template> </xsl:stylesheet> 

when applied to the provided XML document :

 <manual> <section>A: This is relevant for every type</section> <section t600="no" t800="no">B: This is relevant only for the 737-400</section> <section t800="no">C: This is relevant for 737-400 and 737-600</section> <section t400="no">D: This is relevant for 737-600 and 737-800</section> </manual> 

creates the desired, correct result :

 <manual> <section>A: This is relevant for every type</section> <section>D: This is relevant for 737-600 and 737-800</section> </manual> 

If we replace the current parameter in the transformation :

  <xsl:param name="pInterests"> <interest topic="t800"/> </xsl:param> 

from

  <xsl:param name="pInterests"> <interest topic="t400"/> <interest topic="t600"/> </xsl:param> 

and again apply the modified transformation in the same XML document, we will also get the desired and correct result :

 <manual> <section>A: This is relevant for every type</section> <section>B: This is relevant only for the 737-400</section> <section>C: This is relevant for 737-400 and 737-600</section> <section>D: This is relevant for 737-600 and 737-800</section> </manual> 
+3
source

Source: https://habr.com/ru/post/899368/


All Articles