calvin smith wrote:
The pipeline is attached. [...]

Calvin,

Thanks to the Timetracker WAR you sent me by private email, I was able to find the issue. As expected, it involved faulty SAX. This time the issue was not in a processor, but in a stylesheet. The first stylesheet in the editTimesheetXForm.xpl is doing:

<xsl:stylesheet exclude-result-prefixes="p" version="1.0">
    <xsl:template match="/root/request/request-uri">
        <config>
            ...
        </config>
    </xsl:template>
</xsl:stylesheet>

So when it finds the /root/request/request-uri element, it creates your <config> as expected, but for all the other nodes in the input document that are not under /root/request/request-uri, it executes the XSLT built-in templates. And those templates output the text nodes and the value of attributes. So when running this stylesheet, the output really is <config>...</config> and then a bunch of text nodes before the endDocument(). Those text nodes after the root element is closed are of course not valid and were confusing someone down the line. The fix is simply to use match="/" instead of match="/root/request/request-uri" (there another XPath expression to modify). The updated editTimesheetXForm.xpl is attached.

You might want to check that you don't have a similar problem in other XSLT files.

SAX is great because it both simple and very efficient at runtime. The downside is that we have to deal with this kind of problems from time to time. I found this problem by creating a quick and dirty SAXDebuggerProcessor. When you can add it in a pipeline it works like the identity processor, but it will log all the SAX events that go through. In case you want to use it I have attached the class files. You can declare it in processors.xml with:

    <processor uri="oxf/processor/sax-debugger">
        <class name="org.orbeon.oxf.processor.SAXDebuggerProcessor"/>
    </processor>

And use it in a pipeline with:

    <p:processor uri="oxf/processor/sax-debugger">
        <p:input name="data" href="#filterconfig"/>
        <p:output name="data" id="filterconfigX"/>
    </p:processor>

We are thinking facility in OXF to check the SAX that flows in all the pipelines between processors, and generate an error if something incorrect is detected.

Alex


Attachment: oxf-saxdebugger.zip
Description: Zip archive

<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: editTimesheetXForm.xpl,v 1.11 2003/10/23 18:13:05 calvins Exp $ -->
<p:config xmlns:p="http://www.orbeon.com/oxf/pipeline"; xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
	<p:param type="input" name="instance"/>
	<p:param type="output" name="data"/>

	<!-- get requested uri in order to parse out timesheet ID -->
	<p:processor uri="oxf/processor/request">
		<p:input name="config">
<!-- debug="editTimesheetXForm:request" -->
			<config>
				<include>/request/request-uri</include>
<!-- /request/parameters/parameter[name='ID'] -->
			</config>
		</p:input>
		<p:output name="data" id="request"/>
<!-- debug="editTimesheetModel:request"-->
	</p:processor>
	
	<p:processor uri="oxf/processor/pipeline">
		<p:input name="config" href="oxf:/app/pipelines/getApplicationRole.xpl"/>
		<p:output name="data" id="role"/>
	</p:processor>
	
	<p:processor uri="oxf/processor/saxon7">
		<p:input name="data" href="aggregate('root', #request, #role, oxf:/app/config/application.xml#xpointer(/Configuration/RoleStateMappingList) )"/>
        <p:input name="config">
            <xsl:stylesheet exclude-result-prefixes="p" version="1.0">
                <xsl:template match="/">
                    <xsl:variable name="role" select="/root/TTRole/request-security/role[last()]"/>
                    <config>
                        <xsl:if test="/root/TTRole/User/EmployeeID">
                            <EmployeeIDList>
                                <xsl:copy-of select="/root/TTRole/User/EmployeeID"/>
                            </EmployeeIDList>
                        </xsl:if>
                        <TimesheetIDList>
                            <TimesheetID>
                                <xsl:value-of select="substring-after(/root/request/request-uri,'editTimesheet/')"/>
                            </TimesheetID>
                        </TimesheetIDList>
                        <xsl:copy-of select="/root/RoleStateMappingList/RoleStateMapping[Role=$role]/StateIDList"/>
                    </config>
                </xsl:template>
            </xsl:stylesheet>
        </p:input>
		<p:output name="data" id="filterconfig"/>
	</p:processor>

	<!-- Call a sub-pipeline for getting the timesheet instance from the database. -->
	<p:processor uri="oxf/processor/pipeline">
		<p:input name="config" href="oxf:/app/pipelines/filterTimesheets.xpl"/>
		<p:input name="filterconfig" href="#filterconfig"/>
		<p:output name="data" id="dbresponse"/>
	</p:processor>
	
	<!-- build the configuration for the date processor -->
	<p:processor uri="oxf/processor/xslt">
		<p:input name="data" href="#dbresponse"/>
		<p:input name="config">
			<xsl:stylesheet version="1.0" exclude-result-prefixes="p">
				<xsl:template match="Timesheet/Period">
					<config>
						<StartDate>
<xsl:value-of select="Start"/>
</StartDate>
						<EndDate>
<xsl:value-of select="End"/>
</EndDate>
					</config>
				</xsl:template>
			</xsl:stylesheet>
		</p:input>
		<p:output name="data" id="date-config"/>
<!-- debug="editTimesheetXForm:xslt:date-config:output" -->
	</p:processor>
	
	<!-- using the above date-config, ask the date processor for a DateList -->
	<p:processor uri="cde/processor/date">
    	<p:input name="config" href="#date-config"/>
    	<p:output name="data" id="datelist"/>
<!-- debug="editTimesheetXForm:#datelist" -->
   	</p:processor>
	
	<!-- get full list of projects -->
	<p:processor uri="oxf/processor/xslt">
		<p:input name="data" href="oxf:/app/schemas/ProjectEnumerations.xsd"/>
		<p:input name="config">
			<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema"; xmlns:enum="urn:publicid:cde.berkeley.edu:platform:enumerations"; version="1.0" exclude-result-prefixes="p xs enum">
				<xsl:template match="/xs:schema/xs:simpleType/xs:restriction">
					<ProjectList>
						<xsl:for-each select="xs:enumeration">
							<Project>
								<ID>
<xsl:value-of select="@value"/>
</ID>
								<Label>
<xsl:value-of select="xs:annotation/xs:appinfo/enum:Label"/>
</Label>
							</Project>
						</xsl:for-each>
					</ProjectList>
				</xsl:template>
			</xsl:stylesheet>
		</p:input>
		<p:output name="data" id="projectlist"/>
<!-- debug="editTimesheetXForm:xslt:projectlist"-->
	</p:processor>
	
	<!-- check for database success when retrieving timesheet -->
	<p:choose href="#dbresponse">
		<p:when test="not(/Response/@success='false')">
			<!-- build the XForms model -->
			<p:processor uri="oxf/processor/xslt">
				<p:input name="data" href="aggregate('ProjectsAndDatesAndTimesheet',#datelist,#projectlist,#dbresponse)"/>
				<p:input name="config">
					<xsl:stylesheet version="1.0" exclude-result-prefixes="p">
						
						<xsl:key name="TimesheetEntryByProjectKey" match="TimesheetEntry" use="Project"/>
						
						<xsl:template match="/">
							<root>
								<ID>
<xsl:value-of select="/ProjectsAndDatesAndTimesheet/RecordSet/record/documentID"/>
</ID>
								<Matrix>
									<xsl:for-each select="/ProjectsAndDatesAndTimesheet/ProjectList/Project">
										<xsl:variable name="projID" select="ID"/>
										<Project id="{ID}" label="{Label}">
											<xsl:for-each select="/ProjectsAndDatesAndTimesheet/DateList/Date">
												<xsl:variable name="date" select="."/>
												<Time date="{.}">
													<Hours>
													  <!-- Get a nodeset containing the TimesheetEntry elements that match the current project and the current date -->
														<xsl:variable name="entries" select="key('TimesheetEntryByProjectKey',$projID)[Date=$date]"/>
														<!-- If that nodeset is not empty -->
														<xsl:if test="$entries">
														  <!-- Sum all of the Hours elements -->
	  													<xsl:value-of select="sum($entries/Hours)"/>
														</xsl:if>
														<!-- Otherwise, return nothing, NOT 0 (null is different than 0 becuase we are building a sparse Timesheet representation) -->
													</Hours>
												</Time>
											</xsl:for-each>
										</Project>
									</xsl:for-each>
								</Matrix>
							</root>
						</xsl:template>
					</xsl:stylesheet>
				</p:input>
				<p:output name="instance" id="trans-timesheet-data"/>
			</p:processor>
		</p:when>
		<p:otherwise>
			<!-- EVENTUALLY, WE'LL CALL THE ERROR PROCESSOR HERE -->
			<p:processor uri="oxf/processor/identity">
				<!--p:input name="data">
					<ERROR>Error</ERROR>
				</p:input-->
				<p:input name="data" href="#dbresponse"/>
				<p:output name="instance" id="trans-timesheet-data"/>
			</p:processor>
		</p:otherwise>
	</p:choose>
	
	<p:processor uri="oxf/processor/xslt">
		<p:input name="data" href="#trans-timesheet-data"/>
		<p:input name="config" href="oxf:/app/transforms/XFormsWrapper.xsl"/>
		<p:output name="data" ref="data"/>
<!-- debug="editTimesheetXForm:XFormsWrapper:output" -->
	</p:processor>
</p:config>
_______________________________________________
oxf-users mailing list
[EMAIL PROTECTED]
http://mail.orbeon.com/mailman/listinfo/oxf-users

Reply via email to