I am new to XSL. Hence please help me with the below.
I have 2 xmls. I have to do the following in XSL transformation.
if Employee/EmployeeInfo/FirstName = EmployeeSegment/EmployeeSummary/GivenName and Employee/EmployeeInfo/LastName = EmployeeSegment/EmployeeSummary/Surname
employeeId = EmployeeSegment/EmployeeSummary/EmpId
XML1
<Employee>
<EmployeeInfo>
<FirstName>ABC</FirstName>
<LastName>DEF</LastName>
</EmployeeInfo>
</Employee>
XML2
<EmployeeSegment>
<EmployeeSummary>
<EmpId>1234</EmpId>
<GivenName>ABC</GivenName>
<Surname>DEF</Surname>
</EmployeeSummary>
</EmployeeSegment>
I have tried the following. It is not working.
<xsl:param name="cjEmployeeSegment" select="document('CJ_Response.xml')"/>
<xsl:for-each select="/ns3:Employee/ns3:EmployeeInfo">
<xsl:variable name="empFirstName">
<xsl:value-of select="ns1:FirstName"/>
</xsl:variable>
<xsl:variable name="empLastName">
<xsl:value-of select="ns1:LastName"/>
</xsl:variable>
<xsl:for-each select="$cjEmployeeSegment/v32:EmployeeSegment/v31:EmployeeSummary">
<xsl:if test="$empFirstName=v31:GivenName and $empLastName=v31:Surname">
<ns12:EmployeeIdentifier>
<ns12:EmployeeID>
<xsl:value-of select="v31:EmpId"/>
</ns12:EmployeeID>
</ns12:EmployeeIdentifier>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
Assuming you are processing the following input:
XML
<Employee>
<EmployeeInfo>
<FirstName>ABC</FirstName>
<LastName>DEF</LastName>
</EmployeeInfo>
</Employee>
and there is another XML document named CJ_Response.xml:
<EmployeeSegment>
<EmployeeSummary>
<EmpId>1234</EmpId>
<GivenName>ABC</GivenName>
<Surname>DEF</Surname>
</EmployeeSummary>
</EmployeeSegment>
you can use the following stylesheet:
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:param name="cj_Response" select="document('CJ_Response.xml')"/>
<xsl:template match="/Employee">
<root>
<xsl:for-each select="EmployeeInfo">
<xsl:variable name="lookup" select="$cj_Response/EmployeeSegment/EmployeeSummary[GivenName = current()/FirstName and Surname = current()/LastName]" />
<xsl:if test="$lookup">
<EmployeeIdentifier>
<EmployeeID>
<xsl:value-of select="$lookup/EmpId"/>
</EmployeeID>
</EmployeeIdentifier>
</xsl:if>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
to return:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<EmployeeIdentifier>
<EmployeeID>1234</EmployeeID>
</EmployeeIdentifier>
</root>
Of course, this will fail miserably if there are two or more employees with the same name.
Seeking advice on how to calculate the lowerCorner and upperCorner in GML Envelope given an array (coordinates) in the XML. Note I have reduced the list of coordinates significantly to keep short.
Aware I need to iterate the <coordinates> element but unsure most efficient way to calculate the lowerCorner and upperCorner pairs to eventually map into the GML Envelope.
XML Sample
<?xml version="1.0" encoding="UTF-8"?>
<Extract>
<n1:XMLExtract xmlns:n1="urn:com:aaa">
<regionId>4671</regionId>
<coordinates>151.344553 -33.4123250000193, 151.346606 -33.4126370000193, 151.347188 -33.4127280000193, 151.347707 -33.4127990000193, 151.347858 -33.4121160000193, 151.34931 -33.4123270000192, 151.349253 -33.4125910000192, 151.349693 -33.4126610000193, 151.34963 -33.4129810000192, 151.351338 -33.4132280000193, 151.351393 -33.4129550000193, 151.352038 -33.4130480000192, 151.352169 -33.4128100000193, 151.352355 -33.4128370000193, 151.35249 -33.4128910000193, 151.352585 -33.4129170000193, 151.352913 -33.4130080000193, 151.35294 -33.4131310000193, 151.355307 -33.4134860000192, 151.355315 -33.4134470000193, 151.355764 -33.4135020000193, 151.355757 -33.4135590000193, 151.356196 -33.4136240000192, 151.356229 -33.4134890000192, 151.356342 -33.4136260000193, 151.358407 -33.4139280000192, 151.358335 -33.4142510000192, 151.358465 -33.4143660000193, 151.359572 -33.4145260000194, 151.359936 -33.4144860000193, 151.360146 -33.4146080000193, 151.360627 -33.4146790000192, 151.360619 -33.4146980000193, 151.362603 -33.4149980000193, 151.362996 -33.4150940000193, 151.363655 -33.4158080000193, 151.364236 -33.4161380000194, 151.365691 -33.4163460000193, 151.366212 -33.4164920000193, 151.367333 -33.4170870000193, 151.368456 -33.4180250000193, 151.368481 -33.4180200000193, 151.368888 -33.4183130000193, 151.371305 -33.4187840000193, 151.373106 -33.4187890000193, 151.374004 -33.4189970000194, 151.374994 -33.4194460000193, 151.376513 -33.4199650000193, 151.378063 -33.4197680000193, 151.379519 -33.4185780000193, 151.383555 -33.4161210000193, 151.393929 -33.4059400000192, 151.396063 -33.4062720000193, 151.396727 -33.4051740000192, 151.39785 -33.4032380000193, 151.397122 -33.4027200000192, 151.396761 -33.4022700000193, 151.396541 -33.4008350000192, 151.397496 -33.3995910000192, 151.397788 -33.3990280000193, 151.397788 -33.3990100000192, 151.397773 -33.3990000000192, </coordinates>
<interactionId xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1" />
<interactionTypeId xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1" />
<refNumber/>
<incidentNumber/>
<payloadId>20002065</payloadId>
<filename/>
<url/>
</n1:XMLExtract>
</Extract>
Desired output as follows:
<gml:boundedBy>
<gml:Envelope srsDimension="2" srsName="EPSG:4283">
<gml:lowerCorner>-30.511985 151.63592</gml:lowerCorner>
<gml:upperCorner>-30.49207 151.669169</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
Assuming you want to find the coordinates of the rectangle bounding your polygon, and assuming your processor supports the EXSLT extension functions str:split(), math:min() and math:max() (IOW, you are using either libxslt or Xalan), you could do something like:
XSLT 1.0 + EXSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:n1="urn:com:aaa"
xmlns:exsl="http://exslt.org/common"
xmlns:math="http://exslt.org/math"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="exsl math str"
exclude-result-prefixes="n1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Extract">
<xsl:variable name="vertices-rtl">
<xsl:for-each select="str:split(n1:XMLExtract/coordinates, ', ')">
<v x="{substring-before(., ' ')}" y="{substring-after(., ' ')}"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vertices" select="exsl:node-set($vertices-rtl)/v" />
<output>
<lowerLeft>
<xsl:value-of select="math:min($vertices/#x)" />
<xsl:text> </xsl:text>
<xsl:value-of select="math:min($vertices/#y)" />
</lowerLeft>
<upperRight>
<xsl:value-of select="math:max($vertices/#x)" />
<xsl:text> </xsl:text>
<xsl:value-of select="math:max($vertices/#y)" />
</upperRight>
</output>
</xsl:template>
</xsl:stylesheet>
Applied to your example input, the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<lowerLeft>151.344553 -33.4199650000193</lowerLeft>
<upperRight>151.39785 -33.3990000000192</upperRight>
</output>
I am stuck with a XSLT 1.0 problem. I tried to find info on StackOverflow but I couldn't apply the examples.
Here is the structure of my XML:
<XML>
<PR>
<AS>
<ID_AS>AS-001</ID_AS>
<FIRST>
<ID_CATALOG>Id-001</ID_CATALOG>
<STATUS>NOK</STATUS>
</FIRST>
<SECOND>
<ID_CATALOG>Id-002</ID_CATALOG>
<STATUS>OK</STATUS>
</SECOND>
</AS>
<AS>
<ID_AS>AS-002</ID_AS>
<FIRST>
<ID_CATALOG>Id-003</ID_CATALOG>
<STATUS>OK</STATUS>
</FIRST>
<SECOND>
<ID_CATALOG>Id-004</ID_CATALOG>
<STATUS>OK</STATUS>
</SECOND>
</AS>
</PR>
<METADATA>
<ID_CATALOG>Id-001</ID_CATALOG>
<ANGLES>32.25</ANGLES>
</METADATA>
<METADATA>
<ID_CATALOG>Id-002</ID_CATALOG>
<ANGLES>18.75</ANGLES>
</METADATA>
<METADATA>
<ID_CATALOG>Id-003</ID_CATALOG>
<ANGLES>5.23</ANGLES>
</METADATA>
<METADATA>
<ID_CATALOG>Id-004</ID_CATALOG>
<ANGLES>12.41</ANGLES>
</METADATA>
</XML>
I want to display for each AS, the FIRST/ID_CATALOG, FIRST/STATUS and ANGLES corresponding to the ID_CATALOG, then SECOND/etc.
The output would be similar to:
AS-001
Id-001 NOK 32.25
Id-002 OK 18.75
AS-002
Id-003 OK 5.23
Id-004 OK 12.41
I tried the following XSL but I only get the ANGLES for the first item
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns="http://earth.google.com/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:hma="http://earth.esa.int/hma" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" indent="yes" encoding="ISO-8859-1"/>
<!--==================MAIN==================-->
<xsl:template match="/">
<html>
<body>
AS List:
<br/><br/>
<xsl:call-template name="ASandCo"/>
</body>
</html>
</xsl:template>
<!--==================TEMPLATES==================-->
<xsl:template name="ASandCo">
<AS>
<xsl:for-each select="XML/PR/AS">
<xsl:value-of select="ID_AS"/>
<br/>
<xsl:value-of select="FIRST/ID_CATALOG"/> - <xsl:value-of select="FIRST/STATUS"/> -
<xsl:if test="contains(/XML/METADATA/ID_CATALOG, FIRST/ID_CATALOG)">
<xsl:value-of select="/XML/METADATA/ANGLES"/>
</xsl:if>
<br/>
<xsl:value-of select="SECOND/ID_CATALOG"/> - <xsl:value-of select="SECOND/STATUS"/> -
<xsl:if test="contains(/XML/METADATA/ID_CATALOG, SECOND/ID_CATALOG)">
<xsl:value-of select="/XML/METADATA/ANGLES"/>
</xsl:if>
<br/><br/>
</xsl:for-each>
</AS>
</xsl:template>
</xsl:stylesheet>
This XSLT will be applied to very large XML files, so I am trying to find the most efficient way.
Thank you very much in advance!
It seems like you want to look up some metadata metadata based on the ID_CATALOG value.
An efficient way to do this is by using a key. You can define a key on the top level:
<xsl:key name="metadata-by-id_catalog" match="METADATA" use="ID_CATALOG"/>
And then you can look up the ANGLES value using the key for a given ID_CATALOG value like this:
<xsl:value-of select="key('metadata-by-id_catalog', FIRST/ID_CATALOG)/ANGLES"/>
and this:
<xsl:value-of select="key('metadata-by-id_catalog', SECOND/ID_CATALOG)/ANGLES"/>
I have the following xml:
<RootNode xmlns="http://someurl/path/path/path">
<Child1>
<GrandChild1>Value</GrandChild1>
<!-- Lots more elements in here-->
</Child1>
</RootNode>
I have the following xslt:
<xsl:stylesheet version="1.0" xmlns="http://someurl/path/path/path" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="RootNode/Child1">
<NewNodeNameHere>
<xsl:value-of select="GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode >
</xsl:template>
</xsl:stylesheet>
The problem: this is the my result:
<?xml version="1.0" encoding="utf-8"?>
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1 />
</NewRootNode>
I am expecting to see:
<?xml version="1.0" encoding="utf-8"?>
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<NewNodeNameHere>Value</NewNodeNameHere>
<!-- Other new elements with values from the xml file -->
</NewChild1>
</NewRootNode>
I am missing of the information inside of NewChild1 that should be there.
I think my for-each select is correct, so the only thing I can think of is that there is a problem with the namespace in the Xml and the namespace in the xslt. Can anybody see what I'm doing wrong?
The problem is caused by the namespaces.
Since the xml defines xmlns="http://someurl/path/path/path", it is not in the default namespace anymore.
You can define that namespace with an name like xmlns:ns="http://someurl/path/path/path" in the xsl, and then use that name in the XPath expression.
The following works for me:
<xsl:stylesheet version="1.0" xmlns:ns="http://someurl/path/path/path" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="ns:RootNode/ns:Child1">
<NewNodeNameHere>
<xsl:value-of select="ns:GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode >
</xsl:template>
</xsl:stylesheet>
The stylesheet namespace should be http://www.w3.org/1999/XSL/Transform instead of http://someurl/path/path/path.
Also, since the input XML uses a namespace all your XPath expressions should be namespace-qualified:
<xsl:template match="/" xmlns:ns1="http://someurl/path/path/path">
<NewRootNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NewChild1>
<xsl:for-each select="ns1:RootNode/ns1:Child1">
<NewNodeNameHere>
<xsl:value-of select="ns1:GrandChild1"/>
</NewNodeNameHere>
<!-- lots of value-of tags in here -->
</xsl:for-each>
</NewChild1>
</NewRootNode>
</xsl:template>
I have the following XML
<?xml version="1.0" encoding="ISO-8859-1" ?>
- <DEVICEMESSAGES>
<VERSION xml="1" checksum="" revision="0" envision="33050000" device="" />
<HEADER id1="0001" id2="0001" content="Nasher[<messageid>]: <!payload>" />
<MESSAGE level="7" parse="1" parsedefvalue="1" tableid="15" id1="24682" id2="24682" eventcategory="1003010000" content="Access to <webpage> was blocked due to its category (<info> by <hostname>)" />
</DEVICEMESSAGES>
I am using the following xslt
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="DEVICEMESSAGES">
<xsl:value-of select="#id2"/>,<xsl:text/>
<xsl:value-of select="#content"/>,<xsl:text/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
when i use MSXML i just get ,, whereas i want to have something like
id2, content
0001 , Nasher[<messageid>]: <!payload>"
The DEVICEMESSAGES element doesn't have attributes at all.
Change:
<xsl:template match="DEVICEMESSAGES">
to:
<xsl:template match="DEVICEMESSAGES/HEADER">