Reputation: 1091
This is my input xml. The xml can have maximunm three nodes and minimum 1 node. The minimum nodes, the input xml can have, like below
<Root>
<node>uniquename</node>
</Root>
The maximum nodes, the input xml can have is below. Uniquename containing node will be there always.
my sample input xml for the below sample desired output
<Root>
<node>abc</node>
<node>e1</node>
<node>uniquename2</node>
</Root>
The value 'abc' is common for all the input xmls. the value e1, is like a version number. It can have e1 through e9. It can also have a minor version like e1.1 through e9.9. The third node is unique. My output should be the text below, sample below as desired output
Unique name with version from the xml - uniquename2e1
version number - e1
common name - Present in the input
The order of the input xml nodes varies, ie sometimes the version number can come at the top and sometimes the unique name can come at the top. Same is true with the common name. Nevertheless my output should have uniquename followed by version number. In case there is no common name in the input xml, the output text should indicate, it is absent
If the version number is not there in the input, the version number line can be blank from the output
Unique name with version from the xml - uniquename3
common name - Present/Absent in the input.
Though I dont have xslt 2.0 processor, my xslt processor supports xmlns:regexp="http://exslt.org/regular-expressions", I was thinking to use this for finding the versioning part.
EDIT
The unique name is something which is not following the version number pattern ^e\d(\.\d)*$
or not the common name
Upvotes: 1
Views: 77
Reputation: 243459
This XSLT 1.0 transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output method="text"/>
<my:commonAbsent/>
<xsl:variable name="vVer" select=
"/*/node
[starts-with(., 'e')
and
number(substring(.,2)) = number(substring(.,2))]"/>
<xsl:template match="/*">
<xsl:apply-templates mode="unique" select=
"node[not(. = 'abc'
or
generate-id() =generate-id($vVer)
)
]"/>
<xsl:apply-templates select="$vVer" mode="ver"/>
<xsl:apply-templates select=
"node[. = 'abc']
|
document('')
[not(current()/node[.='abc'])]
/*/my:commonAbsent
"/>
</xsl:template>
<xsl:template match="node" mode="unique">
Unique name with version from the xml - <xsl:text/>
<xsl:value-of select="concat(., $vVer)"/>
</xsl:template>
<xsl:template match="node" mode="ver">
Version number - <xsl:value-of select="$vVer"/>
</xsl:template>
<xsl:template match="node[. = 'abc']">
Common name - Present in the input
</xsl:template>
<xsl:template match="my:commonAbsent">
Common name - Absent in the input
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<Root>
<node>abc</node>
<node>e1</node>
<node>uniquename2</node>
</Root>
produces the wanted, correct result:
Unique name with version from the xml - uniquename2e1
Version number - e1
Common name - Present in the input
When the same transformation is applied on an XML document that has no "common name":
<Root>
<node>e1</node>
<node>uniquename2</node>
</Root>
again the correct, wanted result is produced:
Unique name with version from the xml - uniquename2e1
Version number - e1
Common name - Absent in the input
Finally, if the "version" is not represented in the XML document:
<Root>
<node>abc</node>
<node>uniquename2</node>
</Root>
applying the same transformation again produces the wanted, correct result:
Unique name with version from the xml - uniquename2
Common name - Present in the input
Explanation:
The order of the nodes in the result tree (in these case all of them are text nodes) is determined completely by the order of the xsl:apply-templates
instructions that select for execution the templates that produce these result-tree nodes.
Upvotes: 1
Reputation: 12729
I havn't tested this as I don't have access to EXSLT, but this style-sheet should work .. Also there is a lot of scope for improvement in this script, like putting the nodes into variables so that they don't have to be repeatedly calculated and using xsl:choose instead of xsl:if and xsl:if on a not( condition). So consider this the quick and dirty version.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:regexp="http://exslt.org/regular-expressions"
extension-element-prefixes="regexp">
<xsl:import href="regexp.xsl" />
<xsl:output method="text" />
<xsl:template match="/">
<xsl:value-of select="Root/node[.!='abc'][regexp:test(.,'^e\d(\.\d)*$','')]" /><xsl:value-of select="Root/node[regexp:test(.,'^e\d(\.\d)*$','')]" />
<xsl:if test="Root/node[regexp:test(.,'^e\d(\.\d)*$','')]">
version number - <xsl:value-of select="Root/node[regexp:test(.,'^e\d(\.\d)*$','')]" />
</xsl:if>
<xsl:if test="Root/node[.='abc']">
common name - Present in the input
</xsl:if>
<xsl:if test="not( Root/node[.='abc'])">
common name - Absent in the input
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0