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

I want to get GRD with lowest InternalPartyID?

I want to get GRD with lowest InternalPartyID?

(OP)
I want to get a Guardian (GRD) that has the lowest CaseParty@InternalPartyID and where Case/CaseParty/Connection/RemoveDate does not exist.
How do I do this because it has the lowest InternalPartyID = 1614672231
Expected result should be like this

CODE --> xml

<CaseParty ID="16769136" InternalCasePartyID="1634788175" InternalPartyID="1614672231">
			<Connection Word="GRD" BaseConnection="GD" ID="36381880" InternalCasePartyConnectionID="1636470565">
				<Description>Guardian</Description>
				<TimestampCreate>2/18/2015 4:27:54 PM</TimestampCreate>
				<DateAdded>02/18/2015</DateAdded>
			</Connection>
			<CasePartyName Current="true" ID="10052180" InternalNameID="1615525304">
				<NameType>Standard</NameType>
				<NameFirst>Cindee</NameFirst>
				<NameLast>Truesdell</NameLast>
				<FormattedName>Truesdell, Cindee</FormattedName>
			</CasePartyName>
		</CaseParty> 

my xml doc

CODE --> xml

<Integration xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:tsg="http://tsgweb.com" xmlns:IXML="http://tsgweb.com" xmlns:CMCodeQueryHelper="urn:CMCodeQueryHelper" PackageID="BCA PO Notification" MessageID="66595889" xmlns="">
	<Case InternalID="1617088771" ID="12122866" xmlns:user="http://tylertechnologies.com">
		<CaseParty ID="16769136" InternalCasePartyID="1634788175" InternalPartyID="1614672231">
			<Connection Word="GRD" BaseConnection="GD" ID="36381880" InternalCasePartyConnectionID="1636470565">
				<Description>Guardian</Description>
				<TimestampCreate>2/18/2015 4:27:54 PM</TimestampCreate>
				<DateAdded>02/18/2015</DateAdded>
			</Connection>
			<CasePartyName Current="true" ID="10052180" InternalNameID="1615525304">
				<NameType>Standard</NameType>
				<NameFirst>Cindee</NameFirst>
				<NameLast>Truesdell</NameLast>
				<FormattedName>Truesdell, Cindee</FormattedName>
			</CasePartyName>
		</CaseParty>
		<CaseParty ID="16769137" InternalCasePartyID="1634788180" InternalPartyID="1614672232">
			<SendNotice>true</SendNotice>
			<RestrictView>false</RestrictView>
			<ObservedRace Word="H">Native Hawaiian or Other Pacific Islander</ObservedRace>
			<Connection Word="GRD" BaseConnection="GD" ID="36381885" InternalCasePartyConnectionID="1636470570">
				<Description>Guardian</Description>
				<TimestampCreate>2/18/2015 4:35:31 PM</TimestampCreate>
				<DateAdded>02/18/2015</DateAdded>
			</Connection>
			<CasePartyName Current="true" ID="10052181" InternalNameID="1615525305">
				<NameType>Standard</NameType>
				<NameFirst>Regina</NameFirst>
				<NameLast>Sedar</NameLast>
				<FormattedName>Sedar, Regina</FormattedName>
			</CasePartyName>
		</CaseParty>
	</Case>
</Integration> 

RE: I want to get GRD with lowest InternalPartyID?

This seems to be another application of the technique I illustrated in thread426-1744439: How do I find the Plea Event Sequence with highest number.

CODE --> XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
				xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
				xmlns:tsg="http://tsgweb.com" 
				xmlns:IXML="http://tsgweb.com" 
				xmlns:CMCodeQueryHelper="urn:CMCodeQueryHelper"
                exclude-result-prefixes="tsg IXML msxsl CMCodeQueryHelper">

	<xsl:template match="/">
		<xsl:for-each select="//CaseParty[Connection/@Word = 'GRD'][count(Connection/RemoveDate) = 0]">
			<xsl:sort select="@InternalPartyID " data-type="number" order="ascending"/>
			<xsl:if test="position() = 1">
				<xsl:copy-of select="."/>
			</xsl:if>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet> 
The xsl:for-each, selects all CaseParty nodes that have within them a Connection node that has itsWord attribute equal GRD, and also hase no child element named RemoveDate. (Inside the for-each, the context will be a CaseParty node.)

The xsl:sort modifies the default node order for the for-each (which is document order), and gets the node having the lowest InternalPartyID numeric value to the first position in the node set.

The xsl:if causes only the first node, viz the one with the lowest InternalPartyID, to be further processed.

The xsl:copy-of copies the selected node(s) to the output result tree. In this case, since select=".", the single CaseParty that has a guardian (GRD) with the lowest InternalPartyID value is copied in its entirety.

Tom Morrison
Hill Country Software

RE: I want to get GRD with lowest InternalPartyID?

(OP)
Tom thanks for the help. The only problem is that (I should have stated it before hand) I am calling a Guardian template) when the conditions are met. I have attached the xslt code because it is long to past here.
Here is the output I get when using what you suggested.
Let me know if you suggested anything more from me.

CODE --> xml

<CaseParty ID="16769136" InternalCasePartyID="1634788175" InternalPartyID="1614672231" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:tsg="http://tsgweb.com" xmlns:IXML="http://tsgweb.com" xmlns:CMCodeQueryHelper="urn:CMCodeQueryHelper" xmlns:user="http://tylertechnologies.com">
				<SendNotice>true</SendNotice>
				<RestrictView>false</RestrictView>
				<ObservedRace Word="H">Native Hawaiian or Other Pacific Islander</ObservedRace>
				<Connection Word="GRD" BaseConnection="GD" ID="36381880" InternalCasePartyConnectionID="1636470565">
					<Description>Guardian</Description>
					<TimestampCreate>2/18/2015 4:27:54 PM</TimestampCreate>
					<DateAdded>02/18/2015</DateAdded>
				</Connection>
				<CasePartyName Current="true" ID="10052180" InternalNameID="1615525304">
					<NameType>Standard</NameType>
					<NameFirst>Cindee</NameFirst>
					<NameLast>Truesdell</NameLast>
					<FormattedName>Truesdell, Cindee</FormattedName>
				</CasePartyName>
				<TimestampCreate>2/18/2015 4:27:54 PM</TimestampCreate>
			</CaseParty>
			<ext:Guardian>
				<ext:PersonBirthDate/>
				<ext:PersonRaceCode>H</ext:PersonRaceCode>
			</ext:Guardian>
			<ext:Guardian>
				<ext:PersonBirthDate/>
				<ext:PersonRaceCode>H</ext:PersonRaceCode>
			</ext:Guardian> 

Here is what I want instead

CODE --> xml

<ext:Guardian>
	<ext:AddressReference ext:currentIndicator="true">
		<nc:LocationReference s:ref="INT17101998"/>
			</ext:AddressReference>
			<ext:PersonBirthDate ext:approximateDateIndicator="false" ext:currentIndicator="true">1963-07-29</ext:PersonBirthDate>
			<nc:PersonName>
				<nc:PersonGivenName>Kimberly</nc:PersonGivenName>
				<nc:PersonMiddleName>Jean</nc:PersonMiddleName>
				<nc:PersonSurName>Yuhala</nc:PersonSurName>
				<nc:PersonNameSuffixText/>
				<nc:PersonFullName>Yuhala, Kimberly Jean</nc:PersonFullName>
			</nc:PersonName>
	<ext:PersonRaceCode>B</ext:PersonRaceCode>
</ext:Guardian> 

RE: I want to get GRD with lowest InternalPartyID?

[Sorry, the data in the last post seems not to match anything in earlier posts.]

My example shows how to obtain the context of the desired node (namely, CaseParty). Without more time to study your XSLT, which I don't have, I am not sure where the requirement stated in the original post, or this most recent post, might fit in.

However, once you are in the context of CaseParty, you can use normal XSLT techniques to pull information into the output result tree. For example, from the context of CaseParty, the XPath expression (that you might use in <xsl:value-of>, for example) for the first name would be:

CODE --> XPath

CasePartyName/NameFirst 

Also, the sorting technique can apply to <xsl:apply-templates> (typed, not tested):

CODE --> XSLT

<xsl:apply-templates mode="outputGuardian" select="//CaseParty[Connection/@Word = 'GRD'][count(Connection/RemoveDate) = 0]">
<xsl:sort select="@InternalPartyID " data-type="number" order="ascending"/>
</xsl:apply-templates> ... <xsl:template match="CaseParty" mode="outputGuardian">
<xsl:if test="position() = 1">
<!-- place code here to output the desired info from the selected CaseParty node, for example --> <nc:PersonName>
<nc:PersonGivenName><xsl:value-of select="CasePartyName/NameFirst"/></nc:PersonGivenName>
</nc:PersonName>
</xsl:if>
</xsl:template>

Tom Morrison
Hill Country Software

RE: I want to get GRD with lowest InternalPartyID?

Thanks for the star.

Was there one piece of information you found particularly useful for solving your problem? Just would like to know...

RE: I want to get GRD with lowest InternalPartyID?

(OP)
k5tm...based on your last suggestion, I modified my code to the following and I am getting the GRD with the lowest ID
Here is my modified code

CODE --> xml

<xsl:for-each select="//CaseParty[Connection[(@Word='GRD') and (not(RemovedDate))]]">
	<xsl:if test="(count(//CaseParty[(Connection[(@Word='GRD') and (not(RemovedDate))]) and (@InternalPartyID<current()/@InternalPartyID)]))=0">
	<xsl:for-each select="//Party[@InternalPartyID=current()/@InternalPartyID]">
	<xsl:call-template name="Guardian"/>
	</xsl:for-each>
	</xsl:if>
</xsl:for-each> 

RE: I want to get GRD with lowest InternalPartyID?

I am going to risk giving some unsolicited advice based on your modified code. While I hope that you might consider the reasoning and use the methods I demonstrated, I really feel that your original question is generally applicable to a wider audience, and i want others that may happen along to know why I used what I did.

XPath Predicates

My example was coded as:

CODE --> XPath

//CaseParty[Connection/@Word = 'GRD'][count(Connection/RemoveDate) = 0] 
You recoded this as:

CODE --> XPath

//CaseParty[Connection[(@Word='GRD') and (not(RemovedDate))]] 
Rather than nesting predicates (the expressions contained in square brackets), as you did, I 'stacked' the predicates one after the other. You basically used the booleand operator and where I simply added another predicate.

Consider how predicates operate in this example. First the node-set //CaseParty is created. Then the first predicate is applied to that node-set, creating another node-set. In your case, there is only one predicate operating on the //CaseParty node-set; your second predicate is evaluated multiple times (once per CaseParty node) before the outer node-set can be determined.

In my example, the first predicate is applied, creating a temporary node-set, and then the second predicate is applied to that first temporary result (presumably fewer than all the CaseParty nodes in the document), giving the final node-set.

So, you may think that this is merely a matter of style, and that there is no difference in the final result. And, for this particular situation, that is true. (In my minds eye, I imagine the 'stacked' predicates to be more efficient, and they are certainly easier to read left-to-right.)

But there is a trap waiting for the unwary. Remember that the nodes in the node-set are in 'document order' unless sorted or otherwise coerced into a different order (more about which later). So, one has to be careful when using the position() function. To illustrate the trap, let's replace the second predicate with [position()=1], which can be abbreviated [1]:

CODE --> XPath

//CaseParty[Connection/@Word = 'GRD'][1] 
versus:

CODE --> XPath

//CaseParty[Connection[(@Word='GRD') and position()=1]] 
versus:

CODE --> XPath

//CaseParty[Connection[(@Word='GRD')] and position()=1] 

Note that these are not equivalent. The first returns the first //CaseParty node in document order that has a node satisfying Connection/@Word = 'GRD'. The second example will return only those nodes where the first Connection node in document order is the qualifying Connection child node. The third example will return a node only if the first CaseParty node in document order has a qualifying Connection child node.

I strongly urge the use of the 'stacked' predicate technique to filter node-sets for readability, efficiency and predictability.

(Note: there is another use of predicates where the predicate is applied at the 'step' level of an XPath expression such as /main/subnode[predicate1]/nextlevel[predicate2]/*[1]. This is really another topic, that involves understanding the axis being applied at each step in the XPath expression.)

Use xsl:sort to re-order node-sets out of document order

Your outer xsl:for-each uses the // operator in the XPath expression. The // operator requires a full document scan. Sometimes that can't be helped, and as you observe, I used it too.

However, in order to avoid xsl:sort (apparently) you ended up using the // operator twice inside the outer xsl:for-each. Now only the xsl:if is going to be evaluated in each iteration, so you are essentially turning an order N loop into an order N2 loop. In small input documents, who cares... I have seen careless use of the // operator turn milliseconds into minutes on larger documents.

But the xsl:sort will reorder a node-set (which is merely an array of pointers in the processors memory) with far fewer comparisons.

Conclusion

XSLT is essentially a declarative language. Most programmers come to XSLT from procedural programming education and experience, and sometimes trying to force-fit procedural paradigms onto XSLT just doesn't do the language justice. Certainly some of my earlier examples on this very forum show just how ugly it can get, but a few years of experience, studying the examples of the masters, has helped me move between the two programming paradigms quite a bit more easily.

Tom Morrison
Hill Country Software

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