How to pass dynamic separator in , here i passed '|' as static , when i declare variable in xsl and used this place it gives error.
<xsl:variable name="separator" select="'|'"/>
<xsl:key name="key-before" match="result" use="substring-before(Store, $separator)"/>
input XML
<?xml version="1.0" encoding="iso-8859-1"?>
<results>
<result>
<Store>0180|1</Store>
</result>
<result>
<Store>0180|2</Store>
</result>
<result>
<Store>0181</Store>
</result>
<result>
<Store>0183</Store>
</result>
<result>
<Store>abc</Store>
</result>
<result>
<Store>def</Store>
</result>
<result>
<Store>0181|2</Store>
</result>
<result>
<Store>0180|3</Store>
</result>
<result>
<Store>0181|1</Store>
</result>
</results>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="key-direction" select="'p'"/>
<xsl:param name="separator" select="results/sep"/>
<xsl:variable name="demo" select="substring-before(Store,$separator)"/>
<xsl:key name="group-before" match="/results/result" use="substring-before(Store,$demo)" />
<xsl:key name="group-after" match="/results/result" use="substring-before(Store,$demo)" />
<xsl:template match="/results">
<xsl:choose>
<xsl:when test="$key-direction='p'">
<xsl:apply-templates select="result[generate-id() = generate-id(key('group-before', substring-before(Store,$separator))[1])]"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="result[generate-id() = generate-id(key('group-after', substring-before(Store,$separator))[1])]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="result">
<xsl:choose>
<xsl:when test="$key-direction='p'">
<xsl:for-each select="key('group-before', substring-before(Store,$separator))">
<xsl:choose>
<xsl:when test="contains(Store,'|')">
<td>
<xsl:value-of select="substring-before(Store,$separator)"/>
<xsl:value-of select="'|'"/>
<xsl:value-of select="position()"/>
</td>
</xsl:when>
<xsl:otherwise>
<td><xsl:value-of select="Store"/></td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="key('group-after', substring-after(Store,$separator))">
<xsl:choose>
<xsl:when test="contains(Store,'|')">
<td>
<xsl:value-of select="substring-after(Store,$separator)"/>
<xsl:value-of select="'|'"/>
<xsl:value-of select="position()"/>
</td>
</xsl:when>
<xsl:otherwise>
<td><xsl:value-of select="Store"/></td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
What you ask for is not possible (in XSLT 1.0). Neither the match nor the use attribute of xsl:key can contain a reference to a variable.
Related
I was stuck with validation. i can validation when empty string, and validation with length requirement, and validation with just numeric, But when the input was have a special character and have contains alphanumeric. i was stuck. can anyone helping me correct which side i need fix with my code
MYCODE :
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="LOCAL_XSLT_Validate" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
<OperationValueRegex>
<xsl:call-template name="values">
<xsl:with-param name="vals" select="//OperationValueRegex/Value"/>
</xsl:call-template>
</OperationValueRegex>
</xsl:template>
<xsl:template name="values">
<xsl:param name="vals"/>
<xsl:choose>
<!-- Validation Number -->
<xsl:when test="fn:tokenize($vals, ' ')[matches(., '\d+')] and string-length($vals) = 8">
<Result1>
<xsl:value-of select="$vals"/>
</Result1>
</xsl:when>
<xsl:when test="$vals = 'NaN' or string-length($vals) != 8">
<Result1>
<Value>
<xsl:value-of select="$vals"/>
</Value>
<notification>input was not valid requirement maximum</notification>
</Result1>
</xsl:when>
<xsl:otherwise>
<Result1>
<Value>
<xsl:value-of select="$vals"/>
</Value>
<notification>Wrong Format</notification>
</Result1>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
</localEntry>
Request and expected result
{
"OperationValueRegex" : {
"Value" : "1234asdv"
}
}
<OperationValueRegex xmlns="http://ws.apache.org/ns/synapse" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<Result1>1234asdv</Result1>
<notification>Wrong Format</notification>
</OperationValueRegex>
Thanks
I can found the way for validation Alphanumeric
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="LOCAL_XSLT_Validate" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
<OperationValueRegex>
<xsl:call-template name="values">
<xsl:with-param name="vals" select="//OperationValueRegex/Value"/>
</xsl:call-template>
<xsl:call-template name="dates">
<xsl:with-param name="dats" select="//OperationValueRegex/Date"/>
</xsl:call-template>
</OperationValueRegex>
</xsl:template>
<xsl:template name="values">
<xsl:param name="vals"/>
<xsl:choose>
<!-- Validation Number -->
<xsl:when test="fn:matches($vals, '^\d+$') and string-length($vals) = 8">
<Result1>
<xsl:value-of select="$vals"/>
</Result1>
</xsl:when>
<xsl:when test="$vals = 'NaN' or string-length($vals) != 8">
<Result1>
<Value>
<xsl:value-of select="$vals"/>
</Value>
<notification>input was not valid requirement maximum</notification>
</Result1>
</xsl:when>
<xsl:when test="fn:matches($vals, '^[a-zA-Z0-9_]*$') and string-length($vals) > 0">
<Value>
<xsl:value-of select="$vals"/>
</Value>
<notification>Wrong Format</notification>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="dates">
<xsl:param name="dats"/>
<xsl:variable name="dateString">
<xsl:value-of select="substring($dats,1,4)"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="substring($dats,5,2)"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="substring($dats,7,2)"/>
</xsl:variable>
<RequiredFormat>
<xsl:value-of select="format-date(xs:date($dateString), '[Y]/[M]/[D]')"/>
</RequiredFormat>
<OtherFormat>
<xsl:value-of select="format-date(xs:date($dateString), '[MNn] [D], [Y]')"/>
</OtherFormat>
</xsl:template>
</xsl:stylesheet>
</localEntry>
But I still have trouble with when input was have special character like = "#+./!~`*%^$()-#". Need little more help about this
I have the following XML which contains the order details in single element.
<?xml version="1.0" encoding="UTF-8"?>
<MESSAGE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MESSAGE_ID>361155</MESSAGE_ID>
<NAME>Header123</NAME>
<HEADERS>
<HEADER>
<ACTION_COUNT>1</ACTION_COUNT>
<ACTION_DESC>
<DAILY_LOAD>
<LOAD_NO>1</LOAD_NO>
<CUSTOMER_NO>09656951</CUSTOMER_NO>
<REFERENCE xsi:nil="1"/>
<SERIAL>450255470000403803</SERIAL>
<ORDERS>
<ORDER>
<ITEM>5000128762885</ITEM>
<DETAILS>4582;Robert and Co;8;5526;SWD</DETAILS>
<EMP_NO>13</EMP_NO>
<USE_BY_DATE>20110611</USE_BY_DATE>
<DEPOT>5000128910035</DEPOT>
</ORDER>
<ORDER>
<ITEM>5000128853613</ITEM>
<DETAILS>5000;Anne and Co;9;2020;ATM</DETAILS>
<EMP_NO>5</EMP_NO>
<USE_BY_DATE>20110613</USE_BY_DATE>
<DEPOT>5000128910035</DEPOT>
</ORDER>
</ORDERS>
</DAILY_LOAD>
</ACTION_DESC>
</HEADER>
</HEADERS>
<LIST_ID>23689</LIST_ID>
<TRAILER>TEST_NEEDED</TRAILER>
</MESSAGE>
I need that to be transformed into the following format.
(only the DAILY_LOAD>ORDERS section should be changed as below)
.....
<ORDERS>
<ORDER>
<ITEM>5000128762885</ITEM>
<ORDER_NO>4582</ORDER_NO>
<CUSTOMER>Robert and Co</CUSTOMER>
<NO_OF_ITEMS>8</NO_OF_ITEMS>
<TOTAL>5526</TOTAL>
<LOCATION>SWD</LOCATION>
<EMP_NO>13</EMP_NO>
<USE_BY_DATE>20110611</USE_BY_DATE>
<DEPOT>5000128910035</DEPOT>
</ORDER>
<ORDER>
<ITEM>5000128853613</ITEM>
<ORDER_NO>5000</ORDER_NO>
<CUSTOMER>Anne and Co</CUSTOMER>
<NO_OF_ITEMS>9</NO_OF_ITEMS>
<TOTAL>2020</TOTAL>
<LOCATION>ATM</LOCATION>
<EMP_NO>5</EMP_NO>
<USE_BY_DATE>20110613</USE_BY_DATE>
<DEPOT>5000128910035</DEPOT>
</ORDER>
</ORDERS>
.....
The transformed XML contains no but it's divided into CUSTOMER, NO_OF_ITEMS, TOTAL and LOCATION. Any suggestion or help will be highly appreciated.
Thank you in advance.
XSLT 1.0
Using tokenizeString template as suggested in Heber.it blog. I have modified the code for producing different tag names depending on recursion level (ORDER_NO, CUSTOMER, NO_OF_ITEMS, etc).
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<!-- replaces order nodes -->
<xsl:template match="ORDER">
<ORDER>
<xsl:call-template name="tokenizeString">
<xsl:with-param name="list" select="./DETAILS"/>
<xsl:with-param name="delimiter" select="';'"/>
<xsl:with-param name="level" select="1"/>
</xsl:call-template>
</ORDER>
</xsl:template>
<!-- copy everything that doesn't match another template -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!-- template to tokenize strings -->
<xsl:template name="tokenizeString">
<!--passed template parameter -->
<xsl:param name="list"/>
<xsl:param name="delimiter"/>
<xsl:param name="level"/>
<xsl:choose>
<xsl:when test="contains($list, $delimiter)">
<xsl:choose>
<xsl:when test="$level = 1">
<ITEM>
<xsl:value-of select="ITEM"/>
</ITEM>
<ORDER_NO>
<xsl:value-of select="substring-before($list,$delimiter)"/>
</ORDER_NO>
</xsl:when>
<xsl:when test="$level = 2">
<CUSTOMER>
<xsl:value-of select="substring-before($list,$delimiter)"/>
</CUSTOMER>
</xsl:when>
<xsl:when test="$level = 3">
<NO_OF_ITEMS>
<xsl:value-of select="substring-before($list,$delimiter)"/>
</NO_OF_ITEMS>
</xsl:when>
<xsl:when test="$level = 4">
<TOTAL>
<xsl:value-of select="substring-before($list,$delimiter)"/>
</TOTAL>
</xsl:when>
</xsl:choose>
<xsl:call-template name="tokenizeString">
<!-- store anything left in another variable -->
<xsl:with-param name="list" select="substring-after($list,$delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
<xsl:with-param name="level" select="$level + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$list = ''">
<xsl:text/>
</xsl:when>
<xsl:otherwise>
<LOCATION>
<xsl:value-of select="$list"/>
</LOCATION>
<EMP_NO>
<xsl:value-of select="EMP_NO"/>
</EMP_NO>
<USE_BY_DATE>
<xsl:value-of select="USE_BY_DATE"/>
</USE_BY_DATE>
<DEPOT>
<xsl:value-of select="DEPOT"/>
</DEPOT>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
XSLT 2.0
Using tokenize function you can do this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<!-- this template replaces order nodes -->
<xsl:template match="ORDER">
<ORDER>
<xsl:variable name="fields" select="tokenize(DETAILS, ';')"/>
<ITEM>
<xsl:value-of select="ITEM"/>
</ITEM>
<ORDER_NO>
<xsl:value-of select="$fields[position()=1]"/>
</ORDER_NO>
<CUSTOMER>
<xsl:value-of select="$fields[position()=2]"/>
</CUSTOMER>
<NO_OF_ITEMS>
<xsl:value-of select="$fields[position()=3]"/>
</NO_OF_ITEMS>
<TOTAL>
<xsl:value-of select="$fields[position()=4]"/>
</TOTAL>
<LOCATION>
<xsl:value-of select="$fields[position()=5]"/>
</LOCATION>
<EMP_NO>
<xsl:value-of select="EMP_NO"/>
</EMP_NO>
<USE_BY_DATE>
<xsl:value-of select="USE_BY_DATE"/>
</USE_BY_DATE>
<DEPOT>
<xsl:value-of select="DEPOT"/>
</DEPOT>
</ORDER>
</xsl:template>
<!-- this template copies everything that doesn't match another template -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I have two param one is for separator and second is for sub
string if p then substring-before otherwise substring-after.
my Input XML .
<?xml version="1.0" encoding="iso-8859-1"?>
<results>
<result>
<Store>0180|1</Store>
</result>
<result>
<Store>0180|2</Store>
</result>
<result>
<Store>0181</Store>
</result>
<result>
<Store>0183</Store>
</result>
<result>
<Store>abc</Store>
</result>
<result>
<Store>def</Store>
</result>
<result>
<Store>0181|2</Store>
</result>
<result>
<Store>0180|3</Store>
</result>
<result>
<Store>0181|1</Store>
</result>
</results>
Xslt if fix=p then substring-before otherwise substring-after on key :
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="name" select="'|'"/>
<xsl:param name="fix" select="'p'"/>
<xsl:choose>
<xsl:when fix='p'>
<xsl:key name="groups" match="/results/result" use="substring-before(Store,'|')" />
</xsl:when>
<otherwise>
<xsl:key name="groups" match="/results/result" use="substring-after(Store,'|')" />
</otherwise>
</xsl:choose>
<
<xsl:template match="/results">
<xsl:choose>
<xsl:when test="$fix='p'">
<xsl:apply-templates select="result[generate-id() = generate-id(key('groups', substring-before(Store,'|'))[1])]"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="result[generate-id() = generate-id(key('groups', substring-after(Store,'|'))[1])]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="result">
<xsl:choose>
<xsl:when test="$fix='p'">
<xsl:for-each select="key('groups', substring-before(Store,'|'))">
<xsl:choose>
<xsl:when test="contains(Store,'|')">
<td>
<xsl:value-of select="substring-before(Store,'|')"/>
<xsl:value-of select="'|'"/>
<xsl:value-of select="position()"/>
</td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:value-of select="Store"/>
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="key('groups', substring-before(Store,'|'))">
<xsl:choose>
<xsl:when test="contains(Store,'|')">
<td>
<xsl:value-of select="substring-after(Store,'|')"/>
<xsl:value-of select="'|'"/>
<xsl:value-of select="position()"/>
</td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:value-of select="Store"/>
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
An xsl:key definition must be at the top level of your stylesheet.
Conversely, xsl:choose cannot be at the top level.
Try this as your starting point;
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="key-direction" select="'before'"/>
<xsl:key name="key-before" match="result" use="substring-before(Store, '|')"/>
<xsl:key name="key-after" match="result" use="substring-after(Store, '|')"/>
<xsl:template match="/results">
<xsl:copy>
<xsl:choose>
<xsl:when test="$key-direction='before'">
<xsl:apply-templates select="result[generate-id()=generate-id(key('key-before', substring-before(Store,'|'))[1])]"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="result[generate-id() = generate-id(key('key-after', substring-after(Store,'|'))[1])]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
<!-- more templates -->
</xsl:stylesheet>
Note also that:
substring-before('abc', '|')
returns an empty string. This means that:
<Store>0181</Store>
and
<Store>0181|1</Store>
are not going to be grouped together, unless you replace:
substring-before(Store, '|')
with:
substring-before(concat(Store, '|'), '|')
I could not find a similar question anywhere, so thats why posting this new question.
I have an XML that I want to read and convert into SQL using XSLT. The trick part is that the XML elements(i.e. the names) are not known and the XSD for the XML is generated on the fly.
But what is known is certain attributes of the elements.
The XML looks like this :
<?xml version="1.0" encoding="UTF-8"?>
<et:ItemRecordList xmlns:et="urn:org:easetech:easytest:schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:org:easetech:easytest:schema ItemRecord.xsd ">
<ItemRecord recordId="idvalue0" tableName="item_record">
<itemId columnName="item_id" idColumn="true" length="36" nullable="false">itemId</itemId>
<databaseInstitution columnName="database_institution" length="255" nullable="false">0</databaseInstitution>
<lastModifiedDate columnName="last_modified_date" length="255" nullable="false">2001-12-31T12:00:00</lastModifiedDate>
</ItemRecord>
</et:ItemRecordList>
I want to use this XML and convert it into an INSERT SQL statement using XXSLT.
I created an XSLT like this :
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/">
<xsl:for-each select="/*/*">
INSERT INTO
<xsl:value-of select="#tableName" />
(
<xsl:for-each select="/*/*/*">
<xsl:variable name="columnName"><xsl:value-of select="#columnName"/></xsl:variable>
<xsl:choose>
<xsl:when test="#columnName">
<xsl:value-of select="$columnName"/>
<xsl:if test="position()!=last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:for-each>
)
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
which gives me the output like this :
INSERT INTO item_record (item_id, database_institution, last_modified_date)
But I don't know how to create the value part of the query. The value is the value we get using
<xsl:value-of select="." />
I tried concatenating the values, but unfortunately concat didnt work for me. I also played around with xsl:variable but couldnt make it work. If someone could help me with the XSLT that I can use to create to output like below that would be really appreciated.
INSERT INTO item_record (item_id, database_institution, last_modified_date) values (itemId,0,2001-12-31T12:00:00)
How about:
<xsl:template match="/">
<xsl:for-each select="/*/*">
<xsl:text>INSERT INTO </xsl:text>
<xsl:value-of select="#tableName" />
<xsl:text> (</xsl:text>
<xsl:for-each select="*[#columnName]">
<xsl:value-of select="#columnName"/>
<xsl:if test="position()!=last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>) values (</xsl:text>
<xsl:for-each select="*[#columnName]">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
The next XSLT will generate the query as wanted
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:variable name="newline" select="'
'" />
<xsl:template match="/">
<xsl:apply-templates select="*/*/#tableName" />
</xsl:template>
<xsl:template match="#tableName">
<xsl:value-of select="concat('INSERT INTO ', ., ' (')" />
<xsl:apply-templates select="parent::*/*/#columnName" />
<xsl:value-of select="') VALUES ('" />
<xsl:apply-templates select="parent::*/*" mode="values" />
<xsl:value-of select="concat(')', $newline)" />
</xsl:template>
<xsl:template match="#columnName">
<xsl:choose>
<xsl:when test="position() = last()">
<xsl:value-of select="." />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(., ', ')" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="values">
<xsl:choose>
<xsl:when test="position() = last()">
<xsl:value-of select="." />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(., ', ')" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
I have sample xml like this:
User
name A
Id 8
User
name B
Id 5
User
name C
Id 16
User
name D
Id 10
...
This is what i expect, if input is
A only --> output should be A.
B only --> output should be B.
A and B only --> output should be B.
Any users other than A and B --> output should be name of user with lowest id.
A, B and other users --> user with lowest id except A and B.
I have tried different variants of below template
<xsl:template name="getPriorityName">
<xsl:for-each select="//*[local-name()='User']">
<xsl:sort select="./*[local-name()='Id']" data-type="number"/>
<xsl:variable name="name">
<xsl:value-of select="./*[local-name()='name']"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$name!='A' and $name!='B'">
<xsl:if test="position()=1">
<xsl:value-of select="$name"/>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
But since i am unable to club name condition with for-each it does not work in case when A and B are there in input
Thanks Jirka :)
I modified the tempalte a little bit and now it looks ok:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/Users">
<xsl:variable name="UsersCount" select="count(User)" />
<xsl:variable name="UsersExceptAB" select="User[Name != 'A' and Name !='B']" />
<xsl:variable name="UsersAB" select="User[Name = 'A' or Name ='B']" />
<xsl:variable name="UserInABWithMinimumId" select="$UsersAB[not($UsersAB/Id < ./Id)]" />
<xsl:variable name="UserExceptABWithMinimumId" select="$UsersExceptAB[not($UsersExceptAB/Id < ./Id)]" />
<result>
<xsl:choose>
<xsl:when test="$UsersExceptAB">
<xsl:copy-of select="$UserExceptABWithMinimumId" />
</xsl:when>
<xsl:when test="$UsersAB">
<xsl:copy-of select="$UserInABWithMinimumId" />
</xsl:when>
<xsl:otherwise>
<xsl:comment>Oops, something is wrong.</xsl:comment>
</xsl:otherwise>
</xsl:choose>
</result>
</xsl:template>
</xsl:stylesheet>
Is there a way i can just assign the name to a variable; let's say; priorityName that i can use later, i have some other logic based on this priorityName in my application. I tried to access name from node, but since what we finally have is a node set(always of size 1 - either UserInABWithMinimumId or UserExceptABWithMinimumId). This is what i tried:
<xsl:variable name="priorityName">
<xsl:choose>
<xsl:when test="$UsersExceptAB">
<xsl:value-of select="$UserExceptABWithMinimumId/User/Name" />
</xsl:when>
<xsl:when test="$UsersAB">
<xsl:value-of select="$UserInABWithMinimumId/User/Name" />
</xsl:when>
<xsl:otherwise>
<xsl:comment>Oops, something is wrong.</xsl:comment>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Thanks!!!
You could try following XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/Users">
<xsl:variable name="UsersCount" select="count(User)" />
<xsl:variable name="UsersExceptAB" select="User[Name != 'A' and Name !='B']" />
<xsl:variable name="UsersExceptABWithMinimumId" select="$UsersExceptAB[not($UsersExceptAB/Id < ./Id)]" />
<result>
<xsl:choose>
<!-- There exists some User with other name than A or B-->
<xsl:when test="$UsersExceptAB">
<xsl:copy-of select="$UsersExceptABWithMinimumId" />
</xsl:when>
<!-- There exists no User with other than A or B but there is a User with name B -->
<xsl:when test="User[Name = 'B']">
<xsl:copy-of select="User[Name = 'B']" />
</xsl:when>
<!-- There is no User with other than A -->
<xsl:when test="User[Name='A']">
<xsl:copy-of select="User[Name = 'A']" />
</xsl:when>
<!-- Probably there is no User -->
<xsl:otherwise>
<xsl:comment>Oops, something is wrong.</xsl:comment>
</xsl:otherwise>
</xsl:choose>
</result>
</xsl:template>
</xsl:stylesheet>
When I used this input
<?xml version="1.0" encoding="UTF-8"?>
<Users>
<User>
<Name>A</Name>
<Id>8</Id>
</User>
<User>
<Name>B</Name>
<Id>9</Id>
</User>
<User>
<Name>C</Name>
<Id>6</Id>
</User>
<User>
<Name>D</Name>
<Id>10</Id>
</User>
<User>
<Name>E</Name>
<Id>11</Id>
</User>
</Users>
(and commented different User for testing purpose) it returned me desired output.