Reading the *next* node in a XML file (via XSL) - foreach

I have a XSL file which uses a loop to read through a certain set of nodes:
Now, I don't know if this is doable .... when I am inside the loop, is it possible to gain access to the "next" node in the loop for some analysis?
Or, if that is not possible, can I selectively read specific node data in another XML file in this loop?
Here is some of the XML data:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<MeetingWorkBook>
<Meeting>
<BibleReadingM StudyPoint="1" StudyPointDescription="Accurate Reading">Name 1</BibleReadingM>
</Meeting>
<Meeting>
<BibleReadingM StudyPoint="2" StudyPointDescription="Accurate Reading">Name 2</BibleReadingM>
<BibleReading1 StudyPoint="3" StudyPointDescription="Accurate Reading">Name 3</BibleReading1>
<StudentTalk1M StudyPoint="4" StudyPointDescription="Accurate Reading">Name 4</StudentTalk1M>
<StudentTalk1MA>Name 5</StudentTalk1MA>
<StudentTalk2M StudyPoint="5" StudyPointDescription="Accurate Reading">Name 6</StudentTalk2M>
<StudentTalk2MA>Name 7</StudentTalk2MA>
<StudentTalk3M StudyPoint="6" StudyPointDescription="Accurate Reading">Name 8</StudentTalk3M>
<StudentTalk3MA>Name 9</StudentTalk3MA>
<StudentTalk11 StudyPoint="7" StudyPointDescription="Accurate Reading">Name 10</StudentTalk11>
<StudentTalk11A>Name 11</StudentTalk11A>
<StudentTalk21 StudyPoint="8" StudyPointDescription="Accurate Reading">Name 12</StudentTalk21>
<StudentTalk21A>Name 13</StudentTalk21A>
<StudentTalk31 StudyPoint="9" StudyPointDescription="Accurate Reading">Name 14</StudentTalk31>
<StudentTalk31A>Name 15</StudentTalk31A>
</Meeting>
<Meeting>
<BibleReadingM StudyPoint="10" StudyPointDescription="Accurate Reading">Name 16</BibleReadingM>
<StudentTalk1M StudyPoint="11" StudyPointDescription="Accurate Reading">Name 17</StudentTalk1M>
<StudentTalk1MA>Name 18</StudentTalk1MA>
<StudentTalk2M StudyPoint="12" StudyPointDescription="Accurate Reading">Name 19</StudentTalk2M>
<StudentTalk2MA>Name 20</StudentTalk2MA>
<StudentTalk3M StudyPoint="13" StudyPointDescription="Accurate Reading">Name 21</StudentTalk3M>
<StudentTalk3MA>Name 22</StudentTalk3MA>
</Meeting>
<Meeting>
<BibleReadingM StudyPoint="14" StudyPointDescription="Accurate Reading">Name 23</BibleReadingM>
<BibleReading1 StudyPoint="15" StudyPointDescription="Accurate Reading">Name 24</BibleReading1>
<StudentTalk1M StudyPoint="16" StudyPointDescription="Accurate Reading">Name 25</StudentTalk1M>
<StudentTalk1MA>Name 26</StudentTalk1MA>
<StudentTalk2M StudyPoint="17" StudyPointDescription="Accurate Reading">Name 27</StudentTalk2M>
<StudentTalk2MA>Name 28</StudentTalk2MA>
<StudentTalk3M StudyPoint="18" StudyPointDescription="Accurate Reading">Name 29</StudentTalk3M>
<StudentTalk3MA>Name 30</StudentTalk3MA>
<StudentTalk11 StudyPoint="19" StudyPointDescription="Accurate Reading">Name 31</StudentTalk11>
<StudentTalk11A>Name 32</StudentTalk11A>
<StudentTalk21 StudyPoint="20" StudyPointDescription="Accurate Reading">Name 33</StudentTalk21>
<StudentTalk21A>Name 34</StudentTalk21A>
<StudentTalk31 StudyPoint="21" StudyPointDescription="Accurate Reading">Name 35</StudentTalk31>
<StudentTalk31A>Name 36</StudentTalk31A>
</Meeting>
</MeetingWorkBook>
So I would like to make a XSL with a for-each loop as mentioned, that can access the next "meeting" node from the "current" meeting node.
Understand? Thanks.

Thanks to #DanielHaley I found out I had to use following-sibling::Meeting[1].
Here is my final script using the following-sibling method:
<xsl:if test="position()!=last()">
<!--No, it is not the last meeting. Show next weeks student assignments.-->
<!--Is next week a special event?-->
<xsl:if test="following-sibling::Meeting[1]/SpecialEvent=0">
<!--No, it is not a special event.-->
Next weeks students are:<br />
Main:<br />
<xsl:value-of select="following-sibling::Meeting[1]/BibleReadingM"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk1M"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk1MA"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk2M"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk2MA"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk3M"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk3MA"/><br />
</xsl:if>
<!--Auxiliary class 1-->
<xsl:if test="following-sibling::Meeting[1]/NumberClasses>=2">
<br />
Auxiliary class 1:<br />
<xsl:value-of select="following-sibling::Meeting[1]/BibleReading1"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk11"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk11A"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk21"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk21A"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk31"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk31A"/><br />
</xsl:if>
<!--Auxiliary class 2-->
<xsl:if test="following-sibling::Meeting[1]/NumberClasses=3">
<br />
Auxiliary class 2:<br />
<xsl:value-of select="following-sibling::Meeting[1]/BibleReading2"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk12"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk12A"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk22"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk22A"/><br />
<xsl:value-of select="following-sibling::Meeting[1]/StudentTalk32"/> / <xsl:value-of select="following-sibling::Meeting[1]/StudentTalk32A"/><br />
</xsl:if>
</xsl:if>

Related

How to access variable defined under for-each loop/If condition in another for each loop

I have to generate the output in sequence and so I wanted to know how to access the variable defined under For-each loop/If condition and then value of select inside another for loop.
As per my example how to access partn and date3? Please help and suggest.
what is the concept for achieving the same..I have tried with-param as well, but didn't work for me.
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:func="myfunc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions" >
<xsl:output method="text" encoding="utf-8" />
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:template match="ZGS/ID">
<xsl:for-each select="E1">
<xsl:if test="PA = 'CE'">
<xsl:variable name="partn" select="PAN"/>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="E13">
<xsl:if test="ID = 033">
<xsl:variable name="date3"
select="substring(DAT,3,8)"/>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="E1E">
<xsl:text>823</xsl:text>
<xsl:text>03</xsl:text>
<xsl:for-each select="E1ED">
<xsl:if test="QU = 012 ">
<xsl:value-of select="BEL"/>
</xsl:if>
</xsl:for-each>
<xsl:value-of select="$partn"/>
<xsl:value-of select="$date3"/>
</xsl:for-each>
</xsl:template>
INPUT:
<?xml version='1.0' encoding='utf-8'?>
<ZGS>
<ID BEGIN="1">
<E1 SEGMENT="1">
<PA>AG</PA>
<NAME>ABC</NAME>
<SP>E</SP>
<AND>0004</AND>
</E1>
<E1 SEGMENT="1">
<PA>RE</PA>
<PAN>IUIOP</PAN>
<NAME>ABC1</NAME>
<SP>EQ</SP>
<AND>0005</AND>
<EKA3 SEGMENT="1">
<QU>009</QU>
</EKA3>
</E1>
<E1 SEGMENT="1">
<PA>CE</PA>
<PAN>PODW</PAN>
<NAME>ABC2</NAME>
<SP>EP</SP>
<AND>0006</AND>
</E1>
<E13 SEGMENT="1">
<ID>001</ID>
<DAT>20190329</DAT>
</E13>
<E13 SEGMENT="1">
<ID>002</ID>
<DAT>20190429</DAT>
</E13>
<E13 SEGMENT="1">
<IDD>033</IDD>
<DAT>20190529</DAT>
</E13>
<E1E>
<E1ED>
</E1ED>
<E1ED>
</E1ED>
</E1E>
In XSLT, variables once declared/defined, they cannot be changed. And exists only in the loop they are defined.
You might not need the xsl:for-each loop here. Instead the variables can be globally defined, so that you can use them where you want in your xslt.
You can try the following:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:func="myfunc"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="text" encoding="utf-8" />
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:variable name="partn" select="/ZGS/ID/E1[PA = 'CE']/PAN" />
<xsl:variable name="date3" select="substring(/ZGS/ID/E13[ID = '033']/DAT,3,8)" />
<xsl:template match="ZGS/ID">
<xsl:for-each select="E1E">
<xsl:text>823</xsl:text>
<xsl:text>03</xsl:text>
<xsl:for-each select="E1ED">
<xsl:if test="QU = 012 ">
<xsl:value-of select="BEL" />
</xsl:if>
</xsl:for-each>
<xsl:value-of select="$partn" />
<xsl:value-of select="$date3" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/jyRYYiu
Using xsl:param, it can be achieved as
<xsl:param name="partn" select="/ZGS/ID/E1[PA = 'CE']/PAN" />
<xsl:param name="date3" select="substring(/ZGS/ID/E13[ID = '033']/DAT,3,8)" />
<xsl:template match="ZGS/ID">
<xsl:for-each select="E1E">
<xsl:text>823</xsl:text>
<xsl:text>03</xsl:text>
<xsl:for-each select="E1ED">
<xsl:if test="QU = 012 ">
<xsl:value-of select="BEL" />
</xsl:if>
</xsl:for-each>
<xsl:for-each select="$partn">
<xsl:value-of select="." />
</xsl:for-each>
<xsl:value-of select="$date3" />
</xsl:for-each>
</xsl:template>
https://xsltfiddle.liberty-development.net/jyRYYiu/1

XML to CSV (Generation of New Date with input Date)

I have a requirement in which I have to generate new date(YYYYMMDD) from the date which is coming in the record(YYYYMMDD) and below is logic for New date creation:
1.If 'MM - 1' = 0, Then make MM -'12', and Year value as YearFromActualDate - 1
2.DD is always '01'
3.If 'MM - 1' != 0, Then MM in output will be 'MM - 1' and Year will remain the same
I have mentioned the Expected Output which will give idea of above mentioned logic.
Please advise.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions" >
<xsl:output method="text" encoding="utf-8" />
<xsl:param name="delim" select="','" />
<xsl:param name="quote" select="'"'" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:value-of select="$quote" />
<xsl:text>Name</xsl:text>
<xsl:value-of select="$quote" />
<xsl:value-of select="$delim" />
<xsl:value-of select="$quote" />
<xsl:text>Date</xsl:text>
<xsl:value-of select="$quote" />
<xsl:value-of select="$delim" />
<xsl:value-of select="$quote" />
<xsl:text>NewDate</xsl:text>
<xsl:value-of select="$quote" />
<xsl:value-of select="$break" />
<xsl:apply-templates select="ID/ED/E1" />
</xsl:template>
<xsl:template match="E1">
<xsl:value-of select="$quote" />
<xsl:value-of select="name"/>
<xsl:value-of select="$quote" />
<xsl:value-of select="$delim" />
<xsl:value-of select="$quote" />
<xsl:value-of select="date"/>
<xsl:value-of select="$quote" />
<xsl:value-of select="$delim" />
<xsl:value-of select="$quote" />
<xsl:variable name="newdate" select="'01'" />
<xsl:variable name="inMonth" select="substring(date,5,2)" />
<xsl:variable name="inputYear" select="substring(date,1,4)" />
<xsl:choose>
<xsl:when test = "$inMonth='01'">
<xsl:variable name="calculatedMonth" select="12"/>
<xsl:value-of select="concat(xs:integer($inputYear) - 1,$calculatedMonth,$newdate)" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="inMonthlength" select="string-length(xs:string(xs:integer($inMonth) - 1))" />
<xsl:if test="xs:integer($inMonthlength) !=2">
<xsl:value-of select="concat($inputYear,concat(0,xs:integer($inMonth) - 1),$newdate)" />
</xsl:if>
<xsl:if test="xs:integer($inMonthlength) =2">
<xsl:value-of select="concat($inputYear,(xs:integer($inMonth) - 1),$newdate)" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$quote"/>
<xsl:if test="following-sibling::*">
<xsl:value-of select="$break" />
</xsl:if>
</xsl:template>
Input:
<ID>
<ED>
<E1>
<name>Eva</name>
<date>20190504</date> (Consider date as YYYYMMDD)
</E1>
<E1>
<name>Alan</name>
<date>20190101</date>
</E1>
</ED>
<ID>
Expected Output:
"Name","Date","NewDate"
"Eva","20190504","20190401"
"Alan","20190101","20181201"
If I've reverse-engineered your algorithm correctly, what you want is the first day of the previous month.
Logically the steps are:
Convert your date to an xs:date value
Take the first day of the current month
Subtract one month.
In practice it's simplest to combine (1) and (2) so you end up with
xs:date(replace($date, '(....)(..)(..)', '$1-$2-01')) - xs:yearMonthDuration('P1M')
and then you can format this date as YYYYMMDD using
format-date($date, '[Y0001][M01][D01]')

Subtraction by decimal number

I have a to subtract the amount -1 based on the condition.Please any one help.
Input:
<JD>
<GP xmlns="">
I xmlns="">
<PK>40</PK>
<A/>
<AMNT>11659650.15</AMNT>
<B/>
<C/>
</I>
<I xmlns="">
<PK>50</PK>
<A/>
<AMNT>11659650.15</AMNT>
<B/>
<C/>
</I>
</GP>
</JD>
Tried with below XSLT and got 1.165964915E7 for 50.
<xsl:for-each select="JD/mo:GP/I">
<xsl:if test="PK='40'">
<xsl:variable name="a" select="AMNT"/>
<xsl:element name="AMT">
<xsl:value-of select="$a"/>
</xsl:element>
</xsl:if>
<xsl:if test="PK='50'">
<xsl:variable name="a" select="AMNT"/>
<xsl:element name="AMT">
<xsl:value-of select="$a - 1"/>
</xsl:element>
</xsl:if>
Considering your given input as following:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<JD>
<GP>
<I>
<PK>40</PK>
<A />
<AMNT>11659650.15</AMNT>
<B />
<C />
</I>
<I>
<PK>50</PK>
<A />
<AMNT>11659650.15</AMNT>
<B />
<C />
</I>
</GP>
</JD>
</Root>
In XSLT 2.0, you can try it using xs:decimal as below:
<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:template match="/Root">
<xsl:for-each select="JD/mo:GP/I">
<xsl:if test="PK='40'">
<xsl:variable name="a" select="AMNT" />
<xsl:element name="AMT">
<xsl:value-of select="$a" />
</xsl:element>
</xsl:if>
<xsl:if test="PK='50'">
<xsl:variable name="a" select="AMNT" />
<xsl:element name="AMT">
<xsl:value-of select="xs:decimal($a) - 1" />
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
In XSLT 1.0, Use the format-number() function:
<xsl:template match="/Root">
<xsl:for-each select="JD/mo:GP/I">
<xsl:if test="PK='40'">
<xsl:variable name="a" select="AMNT" />
<xsl:element name="AMT">
<xsl:value-of select="$a" />
</xsl:element>
</xsl:if>
<xsl:if test="PK='50'">
<xsl:variable name="a" select="AMNT" />
<xsl:element name="AMT">
<xsl:value-of select="format-number($a - 1, '0.##')" />
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>

Aggregate nodes based on conditon under new parent

I have an given XML and I want to convert it in new xml and want to aggregate nodes based on status and orderId.
<?xml version="1.0" encoding="utf-8"?>
<OrderStatusUpdate>
<OrderStatusEvents>
<OrderStatusEvent>
<StoreCode>store1</StoreCode>
<OrderId>Order1</OrderId>
<ItemId>Item1</ItemId>
<OrderStatusDetails>
<OrderStatusDetail>
<OrderStatusEventTimeStamp>2017-03-19 03:37:05</OrderStatusEventTimeStamp>
<StatusName>Cancelled</StatusName>
</OrderStatusDetail>
</OrderStatusDetails>
</OrderStatusEvent>
<OrderStatusEvent>
<StoreCode>Store1</StoreCode>
<OrderId>Order1</OrderId>
<ItemId>Item2</ItemId>
<OrderStatusDetails>
<OrderStatusDetail>
<OrderStatusEventTimeStamp>2017-03-19 03:48:35</OrderStatusEventTimeStamp>
<StatusName>Cancelled</StatusName>
</OrderStatusDetail>
</OrderStatusDetails>
</OrderStatusEvent>
<OrderStatusEvent>
<StoreCode>Store1</StoreCode>
<OrderId>Order1</OrderId>
<ItemId>Item3</ItemId>
<OrderStatusDetails>
<OrderStatusDetail>
<OrderStatusEventTimeStamp>2017-03-19 03:48:35</OrderStatusEventTimeStamp>
<StatusName>Shipped</StatusName>
</OrderStatusDetail>
</OrderStatusDetails>
</OrderStatusEvent>
<OrderStatusEvent>
<StoreCode>Store1</StoreCode>
<OrderId>Order2</OrderId>
<ItemId>Item1</ItemId>
<OrderStatusDetails>
<OrderStatusDetail>
<OrderStatusEventTimeStamp>2017-03-19 03:48:35</OrderStatusEventTimeStamp>
<StatusName>Cancelled</StatusName>
</OrderStatusDetail>
</OrderStatusDetails>
</OrderStatusEvent>
</OrderStatusEvents>
</OrderStatusUpdate>
And I want an output like this. Here I am grouping elements based on status and orderId.
<Orders>
<group name="CANCELLED">
<STATUS ID="CANCELLED" DESCRIPTION="Goods Cancelled">
<ORDER ID="Order1">
<ORDER_ITEM item="item1" />
<ORDER_ITEM item="item2" />
</ORDER>
</STATUS>
<STATUS ID="CANCELLED" DESCRIPTION="Goods Cancelled">
<ORDER ID="Order2">
<ORDER_ITEM item="item1" />
</ORDER>
</STATUS>
</group>
<group name="SHIPPED">
<STATUS ID="SHIPPED" DESCRIPTION="Goods SHIPPED">
<ORDER ID="Order1">
<ORDER_ITEM item="item3" />
</ORDER>
</STATUS>
<group>
</Orders>
I am using the following xslt and it is working fine. Is there any way to improve this.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="OrderStatusUpdate/OrderStatusEvents">
<Orders>
<xsl:for-each-group select="OrderStatusEvent" group-by="OrderStatusDetails/OrderStatusDetail/StatusName">
<xsl:variable name="group-name" select="current-grouping-key()" />
<group name="{current-grouping-key()}">
<xsl:for-each-group select="current-group()" group-by="OrderId">
<xsl:variable name="order-id" select="current-grouping-key()" />
<xsl:element name="STATUS">
<xsl:attribute name="ID"><xsl:value-of select="$group-name" /></xsl:attribute>
<xsl:attribute name="DESCRIPTION">Goods <xsl:value-of select="$group-name" /></xsl:attribute>
<xsl:element name="ORDER">
<xsl:attribute name="ID"><xsl:value-of select="$order-id" /></xsl:attribute>
<xsl:for-each select="current-group()">
<xsl:if test="$group-name = 'Shipped'">
<xsl:call-template name="Shipped">
<xsl:with-param name="nodes">
<xsl:copy-of select="." />
</xsl:with-param>
</xsl:call-template>
</xsl:if>
<xsl:if test="$group-name = 'Cancelled'">
<xsl:call-template name="Cancelled">
<xsl:with-param name="nodes">
<xsl:copy-of select="." />
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:element>
</xsl:for-each-group>
</group>
</xsl:for-each-group>
</Orders>
</xsl:template>
<xsl:template name="Shipped">
<xsl:param name="nodes">
</xsl:param>
<xsl:element name="ORDER_ITEM">
<xsl:attribute name="ID"><xsl:value-of select="$nodes/OrderStatusEvent/ItemId" /></xsl:attribute>
</xsl:element>
</xsl:template>
<xsl:template name="Cancelled">
<xsl:param name="nodes"></xsl:param>
<xsl:element name="ORDER_ITEM">
<xsl:attribute name="ID"><xsl:value-of select="$nodes/OrderStatusEvent/ItemId" /></xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
It is easier to use literal result elements and attribute value templates as long as you don't need to compute element or attribute names at run-time and I don't think you need the two templates and call-template, it suffices to use
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="OrderStatusUpdate/OrderStatusEvents">
<Orders>
<xsl:for-each-group select="OrderStatusEvent" group-by="OrderStatusDetails/OrderStatusDetail/StatusName">
<xsl:variable name="group-name" select="current-grouping-key()" />
<group name="{current-grouping-key()}">
<xsl:for-each-group select="current-group()" group-by="OrderId">
<xsl:variable name="order-id" select="current-grouping-key()" />
<STATUS ID="{$group-name}" DESCRIPTION="Goods {$group-name}">
<ORDER ID="{$order-id}">
<xsl:apply-templates select="current-group()"/>
</ORDER>
</STATUS>
</xsl:for-each-group>
</group>
</xsl:for-each-group>
</Orders>
</xsl:template>
<xsl:template match="OrderStatusEvent">
<ORDER_ITEM ID="{ItemId}"/>
</xsl:template>
</xsl:stylesheet>

How to turn-off showing child items for selected Main Menu items in Umbraco CMS?

In order to explain my issue easier, please first see this photo
On my template I have already configured Top navigation but problem is that I am trying to make new menu Item which will be called 'News' and thing is that I don't want that every out of 99 news items I will publish (in next two months), to be autmatically available as sumbenu child item under 'News'.
As I noticed, most of the configuration is under 'umbTopNavigation.xslt'
]>
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<!-- Input the documenttype you want here -->
<xsl:variable name="level" select="1"/>
<xsl:template match="/">
<ul id="topNavigation">
<li class="home">
<xsl:if test="$currentPage/#id = $currentPage/ancestor-or-self::* [#level=$level]/#id">
<xsl:attribute name="class">home current</xsl:attribute>
</xsl:if>
Home
</li>
<xsl:for-each select="$currentPage/ancestor-or-self::* [#level=$level]/* [#isDoc and string(umbracoNaviHide) != '1']"> <li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">current</xsl:attribute>
</xsl:if>
<a class="navigation" href="{umbraco.library:NiceUrl(#id)}">
<span><xsl:value-of select="#nodeName"/></span>
</a> </li>
</xsl:for-each> </ul>
</xsl:template>
but I can't figure out what exactly I need to change?
Any help is appreciated and many thanks in advance!
MC2012
First macro
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:template match="/">
<xsl:variable name="items" select="$currentPage/ancestor-or-self::* [#isDoc and #level = 2]/* [#isDoc and string(umbracoNaviHide) != '1']"/>
<!-- The fun starts here -->
<xsl:if test="count($items) > 0">
<ul>
<xsl:for-each select="$items">
<li>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Second Macro
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="umbraco.library"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:param name="currentPage" />
<!-- Specify level of the top node for a language (usually 1) -->
<xsl:variable name="level" select="1" />
<!-- Grab the top node -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[#level = $level]" />
<xsl:template match="/">
<ul class="menu">
<!-- Create the Home link -->
<li>
<xsl:if test="$currentPage/#id = $siteRoot/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl($siteRoot/#id)}">
<xsl:value-of select="$siteRoot/#nodeName" />
</a>
</li>
<!-- Process all children of $siteRoot (if any) -->
<xsl:apply-templates select="$siteRoot/*[#isDoc][not(umbracoNaviHide = 1)]" />
</ul>
</xsl:template>
<!-- Generic template for all nav links -->
<xsl:template match="*[#isDoc]">
<li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName" />
</a>
<!-- Render sub menu if necessary -->
<xsl:call-template name="submenu" />
</li>
</xsl:template>
<!-- Template for Inactive links -->
<xsl:template match="*[#isDoc][umbracoNaviInactive = 1]">
<li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<span>
<xsl:value-of select="#nodeName" />
</span>
<!-- Submenu? -->
<xsl:call-template name="submenu" />
</li>
</xsl:template>
<!-- Template checking for, and processing any submenu -->
<xsl:template name="submenu">
<xsl:variable name="subPages" select="*[#isDoc][not(umbracoNaviHide = 1)]" />
<xsl:if test="$subPages">
<ul>
<xsl:apply-templates select="$subPages" />
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Ok - you have two options. A quick hack or a full solution.
The quick hack is to update the second macro where the subnav is called and exclude the subnav being called where it's the news page (and you can include other pages in here too)
In this example I've used node ID 1107 to be the ID of your news page, but you will need to update this with your actual news page ID.
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="umbraco.library"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:param name="currentPage" />
<!-- Specify level of the top node for a language (usually 1) -->
<xsl:variable name="level" select="1" />
<!-- Grab the top node -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[#level = $level]" />
<xsl:template match="/">
<ul class="menu">
<!-- Create the Home link -->
<li>
<xsl:if test="$currentPage/#id = $siteRoot/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl($siteRoot/#id)}">
<xsl:value-of select="$siteRoot/#nodeName" />
</a>
</li>
<!-- Process all children of $siteRoot (if any) -->
<xsl:apply-templates select="$siteRoot/*[#isDoc][not(umbracoNaviHide = 1)]" />
</ul>
</xsl:template>
<!-- Generic template for all nav links -->
<xsl:template match="*[#isDoc]">
<li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName" />
</a>
<!-- Render sub menu if necessary excluding the news pages -->
<xsl:if test="not(#id=1107)">
<xsl:call-template name="submenu" />
</xsl:if>
</li>
</xsl:template>
<!-- Template for Inactive links -->
<xsl:template match="*[#isDoc][umbracoNaviInactive = 1]">
<li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<span>
<xsl:value-of select="#nodeName" />
</span>
<!-- Submenu? -->
<xsl:call-template name="submenu" />
</li>
</xsl:template>
<!-- Template checking for, and processing any submenu -->
<xsl:template name="submenu">
<xsl:variable name="subPages" select="*[#isDoc][not(umbracoNaviHide = 1)]" />
<xsl:if test="$subPages">
<ul>
<xsl:apply-templates select="$subPages" />
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
The proper way to do it would be to add a property to your document type to include a property to say do not list children or similar, and then test for that in the XSLT, but that's a much more involved fix, and for that I suggest you read up a bit more on how XSLTs work. Let me know if you want to go down that route and there are plenty of resources I can direct you to
thanks,

Resources