XSLT: Create a node if it does not exist?

How can I use XSLT to create nodes if they do not exist? I need to insert node <sectionhead> under <group>, but if <group> node does not exist, then I also need to create this.

eg.

Input (node ​​group exists):

<story> <group> <overhead> <l1>overhead</l1> </overhead> <headline> <l1>headline</l1> </headline> </group> <text> <lines> <l1>line</l1> </lines> </text> </story> 

Conclusion:

 <story> <group> <sectionhead /> <overhead> <l1>overhead</l1> </overhead> <headline> <l1>headline</l1> </headline> </group> <text> <lines> <l1>line</l1> </lines> </text> </story> 

Input (node ​​group does not exist):

 <story> <text> <lines> <l1>line</l1> </lines> </text> </story> 

Conclusion:

 <story> <group> <sectionhead /> </group> <text> <lines> <l1>line</l1> </lines> </text> </story> 
+6
source share
3 answers

Try translating the rules in the problem description directly into the template rules:

"I need to insert node <sectionhead> into <group> "

 <xsl:template match="group"> <group> <sectionhead/> <xsl:apply-templates/> </group> </xsl:template> 

"but if the <group> node does not exist, then I also need to create this."

 <xsl:template match="story[not(group)]"> <story> <group> <sectionhead/> </group> <xsl:apply-templates/> </story> </xsl:template> 
+8
source

Here is a complete solution that overrides the rule / identity template for any story element that does not have a child group element:

 <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:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="story[not(group)]"> <xsl:copy> <xsl:apply-templates select="@*"/> <group> <sectionhead /> </group> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> <xsl:template match="group[not(sectionhead)]"> <xsl:copy> <xsl:apply-templates select="@*"/> <sectionhead /> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> 

when it applies to the provided XML document (without group ):

 <story> <text> <lines> <l1>line</l1> </lines> </text> </story> 

the desired, correct result is output:

 <story> <group> <sectionhead/> </group> <text> <lines> <l1>line</l1> </lines> </text> </story> 

when applied to the first XML document (with group that does not have a sectionhead ):

 <story> <group> <overhead> <l1>overhead</l1> </overhead> <headline> <l1>headline</l1> </headline> </group> <text> <lines> <l1>line</l1> </lines> </text> </story> 

the same conversion again leads to the desired correct result:

 <story> <group> <sectionhead/> <overhead> <l1>overhead</l1> </overhead> <headline> <l1>headline</l1> </headline> </group> <text> <lines> <l1>line</l1> </lines> </text> </story> 
+6
source
 <xsl:for-each select="//story/group"> <sectionhead /> <xsl:copy-of select="." /> </xsl:for-each> <xsl:for-each select="//story/text"> <group><sectionhead /></group> <xsl:copy-of select="." /> </xsl:for-each> 

Two phases - ok?

0
source

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


All Articles