0
votes

Edit: While the answer to this question (thanks Tom!) is technically correct from an XPath perspective, MS InfoPath doesn't play nice with the People Picker. Please note that this will not allow you to clear a people picker and reassign the first selected person. InfoPath only clears the pre-existing XML structure after the people picker has been revalidated. This means taking application focus off of the picker and then switching back. It appears that my ultimate goal cannot be accomplished due to technical limitations in MS InfoPath. At that, I hope this proves to be useful to some other newbie out there!

Question: I need to select the first instance of a node or element in a parent node that repeats. (My terminology may be incorrect). Tried adapting expressions from other posts here on stackoverflow to no avail.

Basic situation: Working with a Person/Group picker in MS InfoPath. If someone picks more than one user in the picker field I want to reset it to the first chosen user. Trouble is that there are multiple pickers on the form that use a similar XML structure and so my XPath isn't working...

InfoPath will handle the expressions and use rules to check for the existence of multiple users within the picker.

Here is my sample XML followed by my failing expression:

<?xml version="1.0" encoding="UTF-8"?><?mso-infoPathSolution solutionVersion="1.0.0.24" productVersion="14.0.0" PIVersion="1.0.0.0" href="file:///C:\Documents%20and%20Settings\Chris\Local%20Settings\Application%20Data\Microsoft\InfoPath\Designer3\35e8a7eff4a841a9\manifest.xsf" ?><?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?><my:myFields xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls" xmlns:ma="http://schemas.microsoft.com/office/2009/metadata/properties/metaAttributes" xmlns:d="http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields" xmlns:q="http://schemas.microsoft.com/office/infopath/2009/WSSList/queryFields" xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:dms="http://schemas.microsoft.com/office/2009/documentManagement/types" xmlns:tns="http://microsoft.com/webservices/SharePointPortalServer/UserProfileService" xmlns:s1="http://microsoft.com/wsdl/types/" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-09-06T15:09:43" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-us">
<my:section1>
    <my:group>
        <pc:Person xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
            <pc:DisplayName>Green, John</pc:DisplayName>
            <pc:AccountId>DOMAIN\John.Green</pc:AccountId>
            <pc:AccountType>User</pc:AccountType>
        </pc:Person><pc:Person xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
            <pc:DisplayName>Smith, John</pc:DisplayName>
            <pc:AccountId>DOMAIN\john.smith</pc:AccountId>
            <pc:AccountType>User</pc:AccountType></pc:Person>
    </my:group>
</my:section1>
<my:section2>
    <my:group>
        <pc:Person xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
            <pc:DisplayName>Public, John</pc:DisplayName>
            <pc:AccountId>DOMAIN\John.Q.Public</pc:AccountId>
            <pc:AccountType>User</pc:AccountType>
        </pc:Person><pc:Person xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls">
            <pc:DisplayName>Doe, John</pc:DisplayName>
            <pc:AccountId>DOMAIN\John.Doe</pc:AccountId>
            <pc:AccountType>User</pc:AccountType></pc:Person>
    </my:group>
</my:section2>
</my:myFields>

The following expression returns both DOMAIN\John.Green and DOMAIN\John.Smith...

/descendant::my:section1/my:group/pc:Person/pc:DisplayName[1]

Close but no cigar.

I need two separate expressions; one that selects DOMAIN\John.Green and one that selects DOMAIN\John.Q.Public.

1
How about //my:section1/my:group/pc:Person[1]/pc:DisplayName or //*/my:group/pc:Person[1]/pc:DisplayName (this one selects from all sections at once)toniedzwiedz
@Tom Hey throw that in as an answer and I'll give you credit! I'm amazed at how simple that is; I should have thought of it myself! Thanks again :)Shrout1

1 Answers

2
votes

You're using a predicate in the wrong place.

Your expression,

/descendant::my:section1/my:group/pc:Person/pc:DisplayName[1]

returns a set of pc:DisplayName elements that are the first ones in their corresponding parents (pc:Person elements) so you get DOMAIN\John.Green and DOMAIN\john.smith

It's basically the first DisplayName of each Person in each group of each section1

What you want is the DisplayName of the first Person in each group of each section1, which translates to the following XPath expression: /descendant::my:section1/my:group/pc:Person[1]/pc:DisplayName