xpatch (take 2)

This is a follow up to my previous proposal on xpatch.

Joe has rightly pointed out that XPath is not sufficient to handles XML files where ordering is not guaranteed. For example:

  <attendees>
    <attendee name="Dream" status="Confirmed" />
    <attendee name="Desire" status="No reply" />
  </attendees>

If I want to update Desire's status, but don't know a priori which order these elements will be returned, xpatch won't work:

<xpatch:xpatch xmlns:xpatch="http://guruj.net/2008/02/21/xpatch#" 
  xmlns="http://www.w3.org/2005/Atom">
  <attendees>
    <attendee xpatch:replace="true" xpatch:node="attendee[2]" 
      name="Desire" status="Confirmed" />
  </attendees>
</xpatch:xpatch>

(Remember, the xpatch:node attribute is used to select a sibling.)

However, Joe points out that this can be resolved by using attributes as keys. So instead:

<xpatch:xpatch xmlns:xpatch="http://guruj.net/2008/02/21/xpatch#" 
  xmlns="http://www.w3.org/2005/Atom">
  <attendees>
    <attendee xpatch:replace="true" xpatch:key="@name"
      name="Desire" status="Confirmed" />
  </attendees>
</xpatch:xpatch>

This replaces the xpatch:replace ... xpatch:node syntax. You still need xpatch:node for xpatch:insertAfter ... xpatch:node, however.

The other issue that needs addressing is how the patch knows to use this attribute when building a patch. There's no generic way to determine this in advance, but we could build a file describing the needed keys, thusly:

<xpatch:keys xmlns:xpatch="http://guruj.net/2008/02/21/xpatch#" 
  xmlns="http://www.w3.org/2005/Atom">
  <attendees>
    <attendee xpatch:key="@name" />
  </attendees>
</xpatch:keys>

and then feed this into the patch generation program.