Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old March 24th, 2009, 01:17 PM
Authorized User
 
Join Date: Mar 2009
Posts: 13
Thanks: 0
Thanked 0 Times in 0 Posts
Default XSLT:How to loop through nodes and retrieve attributes values based on some condition

I have a requirement to extract some information from an XML file and generate another xml file. My target nodes are the MeterReadings/Interval and MeterReadings/Consumption
I targeted the meter readings node since it has both Interval and Consumption as children. I firstly, need to grap the "TimestampEnd", which is an attribute of MeterReadings/IntervalData/IntervalSpec. Next, I need to grap the TimeStamp, which is an attribute of the MeterReadings/ConsumptionData/Reading. Once I get these two datetime values, I need to retrieve the Reading timestamp (MeterReadings/ConsumptionData/Reading/@TimeStamp) and Reading Value (MeterReadings/ConsumptionData/Reading/@Value) ONLY if TimestampEnd and TimeStamp are the same AND TouBucket (MeterReadings/ConsumptionData/
ConsumptionSpec/@TouBucket) = "Total" AND MeasurementPeriod MeterReadings/ConsumptionData/ConsumptionSpec/@MeasurementPeriod= "
EndOfIntervalSnapshot"

I later use the two values downstream. Everything seems to be working fine except I can not loop through ConsumptionData node to get values I want.

My xslt
----------
Code:
<?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:variable name="fileName" select="AMRDEF/ScheduleExecution/ScheduleInfo/@Name"/>
<xsl:template match="AMRDEF">
<LODESTARUSAGE>
<xsl:apply-templates/>
</LODESTARUSAGE>
</xsl:template>
<!-- MeterReadings Template -->
<xsl:template match="MeterReadings">
<xsl:variable name="collectionTime" select="@CollectionTime"/>
<xsl:variable name="serialNumber" select="Meter/@SerialNumber"/>
<xsl:variable name="manufacturer" select="Meter/@Description"/>
<xsl:variable name="startTime" select="IntervalData/IntervalSpec/@TimestampStart"/>
<xsl:variable name="channelID" select="IntervalData/IntervalSpec/@Channel"/>
<xsl:variable name="uom" select="IntervalData/IntervalSpec/@UOM"/>
<xsl:variable name="dcflow" select="IntervalData/IntervalSpec/@Direction"/>
<xsl:variable name="stopTime" select="IntervalData/IntervalSpec/@TimestampEnd"/>
<xsl:variable name="spi" select="IntervalData/IntervalSpec/@Interval * 60"/>
<!-- Get Interval Related Consumption Data-->
<xsl:variable name="conReadValue">
<xsl:for-each select="ConsumptionData">
<xsl:variable name="conToubucket" select="ConsumptionData/ConsumptionSpec/@TouBucket"/>
<xsl:variable name="conMeasurePD" select="ConsumptionData/ConsumptionSpec/@MeasurementPeriod"/>
<xsl:variable name="conSumptionReadTime" select="ConsumptionData/Reading/@TimeStamp"/>
<xsl:if test="$conToubucket='Total' and $conMeasurePD='EndOfIntervalSnapshot'">
<xsl:if test="$conSumptionReadTime = $stopTime">
<xsl:value-of select="ConsumptionData/Reading/@Value"/></xsl:if></xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="conReadTime">
<xsl:for-each select="ConsumptionData"><xsl:variable name="conToubucket" select="ConsumptionData/ConsumptionSpec/@TouBucket"/>
<xsl:variable name="conMeasurePD" select="ConsumptionData/ConsumptionSpec/@MeasurementPeriod"/>
<xsl:variable name="conSumptionReadTime" select="ConsumptionData/Reading/@TimeStamp"/>
<xsl:if test="$conToubucket='Total' and $conMeasurePD='EndOfIntervalSnapshot'">
<xsl:if test="$conSumptionReadTime = $stopTime"><xsl:value-of select="ConsumptionData/Reading/@TimeStamp"/>
</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<!-- Will the Direction (DCFLOW) always be Delivered? -->
<xsl:variable name="dFlow">
<xsl:choose>
<xsl:when test="$dcflow='Delivered'">
<xsl:text>D</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>D</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="uomName">
<xsl:choose>
<xsl:when test="$uom='kwh' or $uom='kWh' or $uom='KWH'">
<xsl:text>KWH</xsl:text>
</xsl:when></xsl:choose>
</xsl:variable>
<xsl:variable name="uomCode">
<xsl:choose><xsl:when test="$uomName='KWH'">
<xsl:text>01</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:variable>
<MDMUSAGE>
<xsl:attribute name="METERID"><xsl:value-of select="$serialNumber"/></xsl:attribute>
<xsl:attribute name="HEADERSERIALNUMBER"><xsl:value-of select="$serialNumber"/></xsl:attribute>
<xsl:attribute name="CHANNELID"><xsl:value-of select="$channelID"/></xsl:attribute>
<xsl:attribute name="UOMCODE"><xsl:value-of select="$uomCode"/></xsl:attribute>
<xsl:attribute name="USAGETYPECODE"><xsl:text>INTERVAL</xsl:text></xsl:attribute>
<xsl:attribute name="EFFECTIVEDATE"><xsl:value-of select="$collectionTime"/></xsl:attribute>
<xsl:attribute name="METERMANUFACTURER"><xsl:value-of select="$manufacturer"/></xsl:attribute>
<METERREADS>
<METERREAD>
<xsl:attribute name="SPI"><xsl:value-of select="$spi"/></xsl:attribute>
<xsl:attribute name="STOPVAL"><xsl:value-of select="$conReadValue"/></xsl:attribute><!--<xsl:attribute name="STARTREADTIME"><xsl:value-of select="$startTimeNoZone"/></xsl:attribute> -->
<xsl:attribute name="STOPREADTIME"><xsl:value-of select="$conReadTime"/></xsl:attribute>
<xsl:attribute name="DCFLOW"><xsl:value-of select="$dFlow"/></xsl:attribute>
<!-- Hardcoded DSTPARTICIPANT and TZSTDNAME -->
<xsl:attribute name="DSTPARTICIPANT"><xsl:text>Y</xsl:text></xsl:attribute>
<xsl:attribute name="TZSTDNAME"><xsl:text>EST</xsl:text></xsl:attribute>
<xsl:attribute name="DESCRIPTOR"><xsl:value-of select="$fileName"/></xsl:attribute>
<!-- END OF HARDCODE -->
<INTS>
<xsl:for-each select="IntervalData/Reading">
<xsl:variable name="rawReading">
<xsl:value-of select="@RawReading"/>
</xsl:variable>
<!-- Does DST equals 1 means a good interval -->
<xsl:variable name="intervalStatus">
<xsl:value-of select="QualityFlags/@DST"/>
</xsl:variable>
<I>
<xsl:attribute name="V"><xsl:value-of select="$rawReading"/></xsl:attribute>
<xsl:attribute name="S"><xsl:value-of select="$intervalStatus"/></xsl:attribute>
</I>
</xsl:for-each>
</INTS>
</METERREAD>
</METERREADS>
</MDMUSAGE>
</xsl:template>
</xsl:stylesheet>
Excerpt of xml - too big to fit
---------------------------------------
<AMRDEF Purpose="AMRDataRequest" version="6.1" CreationTime="2009-03-17 12:50:36">
<MeterReadings Irn="7" Source="Remote" SourceName="08225538" SourceIrn="28" Initiator="Schedule" Purpose="NonBilling" CollectionTime="2009-03-17 12:46:21">
<Meter MeterIrn="7" MeterName="08197231" IsActive="true" SerialNumber="08197231" MeterType="REX" Description="G" InstallDate="2008-06-12 12:00:00" RemovalDate="" AccountIdent="" AccountName="" SdpIdent="065402000 0002" Location="" TimeZoneIndex="11" Timezone="(GMT-05:00) Eastern Time (US &amp; Canada)" TimeZoneOffset="0" ObservesDaylightSavings="true" MediaType="900 MHz"/>
<ConsumptionData>
<ConsumptionSpec UOM="kWh" Direction="Delivered" TouBucket="Total" MeasurementPeriod="EndOfIntervalSnapshot" Multiplier="1"/>
<Reading TimeStamp="2009-03-17 12:00:00" Value="31829"/>
</ConsumptionData>
ConsumptionData>
<ConsumptionSpec UOM="kWh" Direction="Delivered" TouBucket="Total" MeasurementPeriod="Current" Multiplier="1"/>
<Reading TimeStamp="2009-03-17 09:00:00" Value="31809"/>
</ConsumptionData>
<IntervalData>
<IntervalSpec UOM="kWh" Direction="Delivered" Interval="30" Channel="1" TimestampStart="2009-03-16 06:30:00" TimestampEnd="2009-03-17 12:00:00" Multiplier="0.01"/>
<Reading TimeStamp="2009-03-16 06:30:00" RawReading="2.99">
<QualityFlags DST="1"/>
</Reading>
<Reading TimeStamp="2009-03-16 07:00:00" RawReading="1.77">
<QualityFlags DST="1"/>
</Reading>

Excertp of Out file
------------------------
Code:
MDMUSAGE METERID="08197231" HEADERSERIALNUMBER="08197231" CHANNELID="1" UOMCODE="01" USAGETYPECODE="INTERVAL" EFFECTIVEDATE="2009-03-17 12:46:21" METERMANUFACTURER="G">
<METERREADS>
<METERREAD SPI="1800" STOPVAL="" STOPREADTIME="" DCFLOW="D" DSTPARTICIPANT="Y" TZSTDNAME="EST" DESCRIPTOR="DailyLPReads">
<INTS>
<I V="2.99" S="1"/>
<I V="1.77" S="1"/>
<I V="2.87" S="1"/>
<I V="2.71" S="1"/>


I need to populate the STOPVAL and the STOPREADTIME attributes in the output
 
Old March 24th, 2009, 01:21 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

<xsl:for-each select="ConsumptionData">
<xsl:variable name="conToubucket" select="ConsumptionData/ConsumptionSpec/@TouBucket"/>

xsl:for-each changes the context node. Within the for-each, your path expressions need to select relative to the context node. You're positioned at a ConsumptionData element, so get rid of that first step in the path expression.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old March 24th, 2009, 01:50 PM
Authorized User
 
Join Date: Mar 2009
Posts: 13
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thank you so much. I appreciate your prompt response





Similar Threads
Thread Thread Starter Forum Replies Last Post
Loop twice, then inside loop select nodes?? JohnBampton XSLT 2 March 9th, 2009 05:21 AM
Count nodes based of if condition suri_1811 XSLT 1 December 7th, 2006 08:00 PM
Grouping based on attributes values Chamkaur XSLT 4 June 21st, 2006 05:51 AM
XPath - Selecting nodes based on attribute values billy_bob_the_3rd XML 4 December 1st, 2004 06:12 PM
XSL-help-sum of nodes baed on a condition skumar80 XSLT 2 November 8th, 2003 10:08 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.