INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

How do I get the right output using template?

How do I get the right output using template?

(OP)
I would like to get correct output but my template is returning wrong output.
Correct output should be

CODE --> xml

<EditReport>
	<MessageIdentification>Case:1097</MessageIdentification>
	<SourceLocation>111</SourceLocation>
	<SourceUser>Tester</SourceUser>
	<EditResult>
		<EditNumber>001</EditNumber>
		<ItemIdentification/>
		<Result>Fail</Result>
	</EditResult>
</EditReport> 

I am getting the following output which is wrong because Result node should say Fail

CODE --> xml

<EditReport>
	<MessageIdentification>Case:1097</MessageIdentification>
	<SourceLocation>111</SourceLocation>
	<SourceUser>Tester</SourceUser>
	<EditResult>
		<EditNumber>001</EditNumber>
		<ItemIdentification/>
		<Result>Pass</Result>
	</EditResult>
</EditReport> 

xml document

CODE --> xml

<Integration>
	<ControlPoint Timestamp="10/13/2016 11:00:15 AM" UserID="Tester"/>
	<Case>
		<CaseNumber>1097</CaseNumber>
		<Court>
			<NodeID>111</NodeID>
		</Court>
	</Case>
	<IntegrationConditions>
		<NotificationEvent notificationType="CasePartyUpdates">CasePartyUpdate</NotificationEvent>
	</IntegrationConditions>
</Integration> 

xslt code

CODE --> xslt

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
	<xsl:output method="xml"/>
	<xsl:variable name="gEditPass">Pass</xsl:variable>
	<xsl:variable name="gEditFail">Fail</xsl:variable>
	<xsl:variable name="gMessageIdentification">Case:<xsl:value-of select="Integration/Case/CaseNumber"/>
	</xsl:variable>
	<xsl:template match="/">
		<EditReport>
			<MessageIdentification>
				<xsl:value-of select="$gMessageIdentification"/>
			</MessageIdentification>
			<SourceLocation>
				<xsl:value-of select="Integration/Case/Court/NodeID"/>
			</SourceLocation>
			<SourceUser>
				<xsl:value-of select="Integration/ControlPoint/@UserID"/>
			</SourceUser>
			<!-- Edit number 001 -->
			<xsl:call-template name="EditPartyUpdate"/>
		</EditReport>
	</xsl:template>
	<!-- E D I T   N U M  B  E  R  001 -->
	<xsl:template name="EditPartyUpdate">
		<xsl:variable name="vPOSendEventCount">
			<xsl:value-of select="count(NotificationEvent[(@notificationType='ProtectionOrder') or (@notificationType='ProtectionOrderInactivation')])>0"/>
		</xsl:variable>
		<xsl:variable name="vPartyUpdateEventCount">
			<xsl:value-of select="count(NotificationEvent[@notificationType='CasePartyUpdates'])>0"/>
		</xsl:variable>
		<xsl:for-each select="Integration/IntegrationConditions/IntegrationCondition/NotificationEvent">
			<EditResult>
				<EditNumber>001</EditNumber>
				<ItemIdentification>
				</ItemIdentification>
				<Result>
					<xsl:choose>
						<xsl:when test="$vPartyUpdateEventCount=0">
							<xsl:value-of select="$gEditFail"/>
						</xsl:when>
						<xsl:otherwise>
							<xsl:value-of select="$gEditPass"/>
						</xsl:otherwise>
					</xsl:choose>
				</Result>
			</EditResult>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet> 

RE: How do I get the right output using template?

I'll assume you missed an <IntegrationCondition> element in the XML you posted.

The values you're assigning to vPartyUpdateEventCount will be "true" or "false", not 0 or any other number, since you're comparing the result from a count() function call against 0.

So, just remove the "> 0" in the select attribute.

RE: How do I get the right output using template?

(OP)
atlopes. I did as you asked me to but I am still getting the same wrong output when my xml document has the following nodes

CODE --> xml

<IntegrationCondition Word="BCAPO" Description="BCA PO Notification">
			<NotificationEvent notificationType="ProtectionOrder" internalProtectionOrderID="12556" protectionOrderNumber="1606232" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:mscef="courts.state.mn.us/extfun" xmlns:msxsl="urn:schemas-microsoft-com:xslt">Signed By Judicial Officer</NotificationEvent>
		</IntegrationCondition> 

RE: How do I get the right output using template?

If I'm understanding it right, the variables must be set inside the cycle, which must be traverse all <IntegrationCondition> elements (not the NotificationEvent). Anyway, your new XML would only affect the value of vPOSendEventCount, not of vPartyUpdateEventCoun, which you are testing in the <xsl:choose> construct.

RE: How do I get the right output using template?

(OP)
My result Pass or Fail should be based on whether or not vPartyUpdateEventCount vPOSendEventCount are greater than zero.
What should I change in xslt code so that it get the value of vPOSendEventCount and vPartyUpdateEventCount?

RE: How do I get the right output using template?

Your EditPartyUpdate template, rewritten (I assume that the fail occurs when both counts are 0):

CODE --> XSLT

<xsl:template name="EditPartyUpdate">
    <xsl:for-each select="Integration/IntegrationConditions/IntegrationCondition">
      <xsl:variable name="vPOSendEventCount">
        <xsl:value-of select="count(NotificationEvent[(@notificationType='ProtectionOrder') or (@notificationType='ProtectionOrderInactivation')])"/>
      </xsl:variable>
      <xsl:variable name="vPartyUpdateEventCount">
        <xsl:value-of select="count(NotificationEvent[@notificationType='CasePartyUpdates'])"/>
      </xsl:variable>
      <EditResult>
        <EditNumber>001</EditNumber>
        <ItemIdentification>
        </ItemIdentification>
        <Result>
          <xsl:choose>
            <xsl:when test="$vPartyUpdateEventCount = 0 and $vPOSendEventCount = 0">
              <xsl:value-of select="$gEditFail"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$gEditPass"/>
            </xsl:otherwise>
          </xsl:choose>
        </Result>
      </EditResult>
    </xsl:for-each>
  </xsl:template> 

RE: How do I get the right output using template?

(OP)
Maybe my question was not clear. There are 4 scenarios, I have numbered them below.
Scenario 1. CasePartyUpdates = 0 and ProtectionOrder = 0 No EditResult (Nothing to display.

Scenario 2. CasePartyUpdates > 0 and ProtectionOrder = 0 EditResult is displayed with <Result>Fail</Result>

Scenario 3. CasePartyUpdates > 0 and ProtectionOrder > 0 EditResult is displayed with <Result>Pass</Result>

Scenario 4. CasePartyUpdates = 0 and ProtectionOrder > 0 EditResult is displayed with <Result>Pass</Result>

RE: How do I get the right output using template?

CODE --> XSLT

<xsl:template name="EditPartyUpdate">
    <xsl:for-each select="Integration/IntegrationConditions/IntegrationCondition">
      <xsl:variable name="vPOSendEventCount">
        <xsl:value-of
          select="count(NotificationEvent[(@notificationType = 'ProtectionOrder') or (@notificationType = 'ProtectionOrderInactivation')])"/>
      </xsl:variable>
      <xsl:variable name="vPartyUpdateEventCount">
        <xsl:value-of select="count(NotificationEvent[@notificationType = 'CasePartyUpdates'])"/>
      </xsl:variable>
      <xsl:if test="$vPOSendEventCount != 0 or $vPartyUpdateEventCount != 0">
        <EditResult>
          <EditNumber>001</EditNumber>
          <ItemIdentification> </ItemIdentification>
          <Result>
            <xsl:choose>
              <xsl:when test="$vPOSendEventCount = 0">
                <xsl:value-of select="$gEditFail"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="$gEditPass"/>
              </xsl:otherwise>
            </xsl:choose>
          </Result>
        </EditResult>
      </xsl:if>
    </xsl:for-each>
  </xsl:template> 

RE: How do I get the right output using template?

(OP)
Thank you so so much. It is now working

RE: How do I get the right output using template?

momo2000,

First, let's go back to your original XSLT.

The first issue, and perhaps the real cause of your confusion, is that of the context node when the call-template processing instruction is encountered. The context is exactly "/". Since the root element is named Integration the counts in the variables will always be zero. The XPath expression begins with NotificationEvent; since the context is "/" the only way for the count to be non-zero is if NotificationEvent were the root element of the document. Mr. Lopes takes this into account by shifting the for-each processing instruction to the beginning of the called template, and states "If I'm understanding it right, the variables must be set inside the cycle...". I have followed Mr. Lopes' lead in my example below, but I have serious reservations it is correct for all inputs (about which more later).

The lesson to be learned from this first issue: when creating a called template, use XML comments to state the expected context of the called template. This comment will then function as a reminder when you are coding the <xsl:call-template> processing instruction. If the context node is not already correct, you can use an xsl:for-each to bracket the xsl:call-template, thereby shifting the context node to that which is correct for the called template.

(Sidebar: The use of xsl:for-each simply to shift context, rather than iterate over multiple nodes, seems to be an unappreciated feature. But it is a remarkably useful feature, often vital to working in environments that have multiple input documents. For example, if you have an alternative input document that is a large table, you would want to use xsl:key so that your table references can be more efficient. But because the key reference has to be made within the context of the indexed document, you have to switch context to that document with a for-each. I have seen a couple DITA processors, for example, where such context shifting is easily as important as nodeset iteration.)

Why do I have reservations about the correctness for all inputs? Your probelm statement seems to indicate that a single output is desired, but the presence of an element that is plural, IntegrationConditions, makes me think that something else is wrong.

Next, and probably not a real issue here, is the practice of using a single xsl:value-of inside the defintion of an xsl:variable. Use instead the select attribute on the xsl:variable itself (as demonstrated below), with the identical value. Your construct actually creates a variable that has multiple text nodes. This usually sorts itself out as the XSLT processor coerces the multiple text nodes into a string that can be converted. But, if you are using a good XSL debugger, instead of seeing a simple integer for a count, you may see instead a tree structure as the value of a variable.

Here is my guess at an XSL approach:

CODE --> XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
	<xsl:output method="xml" indent="yes"/>
	<xsl:variable name="gEditPass">Pass</xsl:variable>
	<xsl:variable name="gEditFail">Fail</xsl:variable>
	<xsl:variable name="gMessageIdentification">Case:<xsl:value-of select="Integration/Case/CaseNumber"/>
	</xsl:variable>
	<xsl:template match="/">
		<EditReport>
			<MessageIdentification>
				<xsl:value-of select="$gMessageIdentification"/>
			</MessageIdentification>
			<SourceLocation>
				<xsl:value-of select="Integration/Case/Court/NodeID"/>
			</SourceLocation>
			<SourceUser>
				<xsl:value-of select="Integration/ControlPoint/@UserID"/>
			</SourceUser>
			<!-- Edit number 001 -->
			<xsl:call-template name="EditPartyUpdate"/>
		</EditReport>
	</xsl:template>
	<!-- E D I T   N U M  B  E  R  001 -->
	<xsl:template name="EditPartyUpdate"><!-- expected context is / -->
		<xsl:for-each select="Integration/IntegrationConditions/IntegrationCondition">
		<xsl:variable name="vPOSendEventCount" 
		              select="count(NotificationEvent[(@notificationType='ProtectionOrder') or (@notificationType='ProtectionOrderInactivation')])"/>
		<xsl:variable name="vPartyUpdateEventCount"
					  select="count(NotificationEvent[@notificationType='CasePartyUpdates'])"/>

		<xsl:comment>  CasePartyUpdates: <xsl:value-of select="$vPartyUpdateEventCount"/>
	    ProtectionOrder:  <xsl:value-of select="$vPOSendEventCount"/>
		Context Node:  <xsl:value-of select="local-name(.)"/></xsl:comment>
		<xsl:if test="not($vPartyUpdateEventCount=0 and $vPOSendEventCount=0)">
				<EditResult>
					<EditNumber>001</EditNumber>
					<ItemIdentification/>
					<Result><xsl:choose>
						    <xsl:when test="$vPartyUpdateEventCount &gt; 0 and $vPOSendEventCount = 0"><xsl:value-of select="$gEditFail"/></xsl:when>
						    <xsl:otherwise><xsl:value-of select="$gEditPass"/></xsl:otherwise>
						    </xsl:choose></Result>
				</EditResult>
		</xsl:if>
			</xsl:for-each>
	</xsl:template>
</xsl:stylesheet> 

Result below. Note that I have left in debugging XML comments. Often you can use such comments to help you determine what is happening.

CODE --> XML

<EditReport xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  <MessageIdentification>Case:1097</MessageIdentification>
  <SourceLocation>111</SourceLocation>
  <SourceUser>Tester</SourceUser>
  <!--  CasePartyUpdates: 1
	    ProtectionOrder:  0
		Context Node:  IntegrationCondition-->
  <EditResult>
    <EditNumber>001</EditNumber>
    <ItemIdentification/>
    <Result>Fail</Result>
  </EditResult>
</EditReport> 

Tom Morrison
Hill Country Software

RE: How do I get the right output using template?

(OP)
Thanks Tom as always for helping me. I did modify your solution a little bit in order for it to work as I wanted it to.
Maybe I need to know how to clearly state in my questions what I am trying to achieve and also show the desired output. I know it makes it easier to get help is the question is clearly explained and the desired output shown/indicated in the question.
I did modify your code a little so that:
1. when (for example)NotificationEvent[notificationType="@CasePartyUpdates"]
the EditResult displays <EditNumber>001</EditNumber> and <Result>Fail</Result>
2. Whenever the NotificationEvent[notificationType="@ProtectionOrder"] the result EditResult displays <EditNumber>001</EditNumber> and <Result>Pass</Result>
3. If the XML document has both NotificationEvent[notificationType="@CasePartyUpdates"] and NotificationEvent[notificationType="@ProtectionOrder"]at the same time, the EditResult will always display <EditNumber>001</EditNumber> and <Result>Pass</Result>
I followed the code atlopes gave as solution.

RE: How do I get the right output using template?

momo200,

I have been in the business of developing and selling software for more than 40 years. For most of that time, my customers were other software vendors (that is, my company sold software tools). From that experience of supporting hundreds of customers, I have come to understand how difficult it is to separate oneself from all the bits and bytes, and be able to describe a problem clearly to someone who has not 'walked the road' with you. I still have to remind myself of that fact when I am the one seeking help on a problem. You are definitely not alone!

By the way, we are still rolling out integrations with eFileTexas, which shares the technology you are using. There are a lot of courts in Texas!

Thanks for the star. Always appreciated.

Tom Morrison
Hill Country Software

RE: How do I get the right output using template?

(OP)
Tom your words are very encouraging. Sometimes I am a little frustrated when I am not able to articulate what I am trying to do. But on the bright side, you have a lot of experience and that helps you understand my questions even when they are not stated in a clear way! Besides you do help without making me feel dumb or stupid or unworthy of your time.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close