RFC 5261
An Extensible Markup Language (XML) Patch Operations Framework Utilizing XML Path Language (XPath) Selectors
An Extensible Markup Language (XML) Patch Operations Framework Utilizing XML Path Language (XPath) Selectors ๐
Network Working Group ๐ธ J. Urpalainen Request for Comments: 5261 ๐ Nokia Category: Standards Track โจ September 2008 ๐ฆ
This doc is an official Standards Track spec, written by J. Urpalainen from Nokia, and it's dated September 2008. The header doesn't list any RFCs it obsoletes or updates, so I'm not claiming any of that. Keep this in mind for the title block ๐
Status of This Memo ๐
okay so this doc is a spec for an Internet standards track protocol ๐ฅ It's basically a request for the Internet community to talk about it and send over suggestions for making it better ๐ฌ If you want to know where this protocol stands officially, check the current version of "Internet Official Protocol Standards" (STD 1). That's the place for the real status ๐ง And the good news is that distribution of this memo is unlimited, so share it with everyone ๐
Abstract ๐ซถ
bestie, XML documents are everywhere ๐ They're the containers people use to swap and store all kinds of data. The annoying part is that if you want to change one, you usually have to send the entire new copy, unless there's a way to say "hey, only these bits changed" ๐ญ This doc gives you exactly that, using XML Path Language (XPath) selectors to point at the spot you want to change. The selector plus the new content is the core of a patch operation โจ Then you've got three basic moves, <add>, <replace>, and <remove>, and you can chain a bunch of patches together to update an existing XML document. Iconic ๐
1. Introduction ๐ง
XML [W3C.REC-xml-20060816] is the big name for these document containers, and they're used all over the place to exchange and store arbitrary data โจ When you need to send changes, the default move is to ship the whole new version, unless you can point at only the parts that changed. Those changed parts are what we call patches ๐ฉน
This doc describes an XML patch framework that uses XPath selectors [W3C.REC-xpath-19991116] ๐ฏ An XPath selector is how you pinpoint the exact portion of the XML you want to touch. The selector values and the new data content are the foundation of every patch operation in here. On top of that, the basic <add>, <replace>, and <remove> directives let you apply a set of patches to update an existing target XML document ๐ With these, you get a simple way to handle data-oriented XML documents [W3C.REC-xmlschema-2-20041028]. So adding, removing, or swapping out elements and attributes is easy peasy ๐ Just to be clear, this is not a full XML diff format ๐ It only gives you the basic patch operation elements, which you can drop into a bigger format that usually has extra semantics of its own.
Here's a real-life example ๐ In the Session Initiation Protocol (SIP) [RFC3903] presence system, a partial PIDF XML document format [RFC5262] is just the normal Presence Information Data Format (PIDF) document combined with the patch operation elements from this doc ๐ฆ Generally, you can use patch operations in any app that trades XML documents, like inside the SIP Events framework [RFC3265] ๐ Another one is XCAP-diff [SIMPLE-XCAP], which uses this framework to send partial updates for changes to XCAP [RFC4825] resources. Literally so useful ๐ญ
2. Conventions ๐
Okay, the BCP 14 key words are the important ones here, so pay attention ๐ค The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119, BCP 14 [RFC2119] and they tell you the requirement levels for compliant implementations ๐ฅ
Next up are the terms the doc uses, so you're not lost later ๐ง
- Target XML document: A target XML document is the one that's going to get updated with a set of patches ๐ฏ
- XML diff document: This is an XML document that holds patch operation elements, namespace declarations, and all the document content changes needed to turn a target XML document into a new patched XML document โจ
- Patched XML document: This is the XML document you get after applying one or more patch operations from the XML diff document to the target XML document ๐
- Patch operation: A single change, a patch that's being applied to update a target XML document ๐ฉน
- Patch operation element: An XML element that stands for one single patch operation ๐ธ
- Type definition for an element: A World Wide Web Consortium (W3C) Schema type definition for an element that describes a patch operation's content ๐
- In-scope namespace declaration: A list of all the in-scope namespace declarations within a context node. The QName (qualified name) expansion of a context node is based on mapping a prefix to one of these declarations. For an element, one namespace binding may have an empty prefix ๐งฉ
- Positional constraint: A number wrapped in square brackets. You can use it as a location step predicate ๐
- Located target node: A node that was found in the target XML document with the help of an XPath selector value ๐
- White space text node: A text node that contains nothing but white space ๐ซง
3. Basic Features and Requirements โจ
okay so here's the vibe ๐ XPath selector values and the new data content live inside XML elements, and the name of the element tells you what to do: <add>, <replace>, or <remove>. ๐ These patch operation elements are defined by schema types written in the W3C Schema language [W3C.REC-xmlschema-1-20041028]. The XPath selectors sit in attributes on those elements and pinpoint the target. The child nodes hold the new data. In general, when it makes sense, the new content SHOULD be moved over unaltered into the patched XML document ๐ฆ
XML docs that are equivalent for a lot of apps MAY look totally different physically ๐ธ The goal here is a deterministic framework where the canonical form with comments [W3C.REC-xml-c14n-20010315] of an XML document decides logical equivalence. For example, white space text nodes MUST be processed properly to make this work, because white space is significant by default [W3C.REC-xml-c14n-20010315]. Be careful with those little gaps, bestie ๐
The specs that reference these element schema types MUST define the full XML diff format with an appropriate MIME type [RFC3023] and a character set, e.g., UTF-8 [RFC3629]. For example, the partial PIDF format [RFC5262] includes this schema and adds extra definitions to make a complete XML diff format for partial presence information updates. It's giving modular ๐งฉ
Since the schema in this document doesn't declare any target namespace, the type definitions inherit the target namespace of the including schema. So you can skip extra namespace declarations inside the XML diff documents. Lowkey so convenient โจ
Apps are expected to define <add>, <replace>, and <remove> elements based on the matching type definitions in this schema. An app may also reference only a subset of these types, which is totally fine ๐ A future extension could bring in other operations. For example, with document-oriented models [W3C.REC-xmlschema-2-20041028], a <move> operation plus a text node patching algorithm combined with <move> would undoubtedly produce smaller XML diff documents. Future us is gonna eat that up ๐
The instance document elements based on these schema type definitions MUST be well formed and SHOULD be valid. No skipping the basics, periodt ๐ซถ
Here's what you can add, replace, or remove with this framework: elements, attributes, namespaces, comments, texts, and processing instructions. The full XML prolog, including things like XML entities [W3C.REC-xml-20060816], and the root node of an XML document can't be patched with this framework. BUT patching comments and processing instructions of the root node is allowed ๐ Removing or adding a document root element is not allowed, because any valid XML document MUST always contain a single root element. Also, heads up: support for external entities is beyond the scope of this framework ๐
4. Patch Operations
An XML diff document holds a collection of patch operation elements, including one or more <add>, <replace>, and <remove> elements. These patch operations get applied one by one in document order. Once the first patch updates a target XML document, the patched document becomes a brand new independent document, and the next patch gets applied to that. This keeps going until every patch has been processed successfully ๐ฅ
4.1. Locating the Target of a Patch
Each patch operation element has a 'sel' attribute. Its value is an XPath selector using a restricted subset of the full XPath 1.0 recommendation. The 'sel' value is used to find a single unique target node in the target XML document. That located node pinpoints the target for a change. Usually it's an element, which either gets updated itself or has some child nodes added into it. It MAY also be something like a comment node, with other sibling nodes inserted after it. Either way, it's an error condition if multiple nodes turn up when the selector gets evaluated. Not it being messy ๐
The XPath selections in the 'sel' attribute always start from the root node of a document. So relative location paths SHOULD be used, which means the starting root node selection "/" can be left out. When you're locating elements in a document tree, a node test can be either a "" character or a QName [W3C.REC-xml-names-20060816]. A "" character selects all element children of the context node. Right after the node test, a location step can have one or more predicates in any order. Attribute value comparisons are one of the most typical predicates ๐ฆ The string value of the current context node or a child element can also be used to identify elements in the tree. The character ".", which marks a current context node selection, is just an abbreviated form of "self::node()". Last but not least, positional constraints like "[2]" can be used as an extra predicate ๐ง
An XPath 1.0 "id()" node-set function MAY also be used to identify unique elements in the document tree. The schema that describes the content model of the document MUST then use an attribute with the type ID [W3C.REC-xmlschema-2-20041028]. Or, with non-validating XML parsers, an "xml:id" [W3C.WD-xml-id-20041109] attribute MUST have been used within an instance document. Very specific, very important ๐
4.2. Namespace Mangling
Okay, so the normal model for namespace prefixes is that they're local in scope ๐ธ That means an XML diff document MAY use different prefixes for the namespaces used in the target document. The agent parsing the diff document MUST resolve prefixes separately in both documents, so the resulting QNames (qualified names) from each one actually match up ๐
The XML diff document MUST contain declarations for all namespaces used in the diff document. The diff document's declarations are always the ones used to decide which namespaces apply inside the diff document. Source of truth, always ๐
4.2.1. Namespaces Used in Selectors
A selector in a diff document may use prefixes when naming elements. If it does use a prefix, that prefix must be looked up in the diff document's namespace declarations.
For example, the patch operation element of a diff document has an
in-scope namespace declaration "xmlns:a='foo:'" with a selector
"sel='a:bar'". The agent processing this patch MUST then look for
a 'bar' element qualified with the 'foo:' namespace regardless of
whether the 'foo:' namespace has a prefix assigned in the target
document or what that prefix is.
Default namespaces make this model a little more complicated ๐ When the diff document has a default namespace declaration, any element selector without a prefix MUST be evaluated using that namespace.
For example, the patch operation element of a diff document has an
in-scope namespace declaration "xmlns='foo:'" with a selector
"sel='bar'". The agent processing this patch MUST then look for a
'bar' element qualified with the 'foo:' namespace, regardless of
whether the 'foo:' namespace has a prefix assigned in the target
document or what that prefix is.
Unqualified names are also a thing ๐ฆ If there's no default namespace declared and an element name shows up without a prefix, then it's an unqualified element name. If that shows up in a selector, it MUST match an unqualified element in the target document.
For example, the patch operation element of a diff document has
only one in-scope namespace declaration "xmlns:a='foo:'" with a
selector "sel='bar'". Since the 'bar' element has no prefix, and
there is no default namespace declaration in scope, the agent
processing this patch can only match the selector against a 'bar'
element that has no prefix and also no default namespace in scope.
4.2.2. Departures from XPath Requirements
Heads up, this is where things get a little plot twisty ๐ The prefix matching rules described earlier in this section are different from the ones required in XPath 1.0 and 2.0 [W3C.REC-xpath20-20070123]. In XPath 1.0, a "bar" selector always locates an unqualified <bar> element. In XPath 2.0, a "bar" selector matches an unqualified <bar> element, AND ALSO a qualified <bar> element that's in scope of a default namespace declaration. In contrast, in this specification, a selector without a prefix only matches one element. It may match an element with or without a prefix, but only if the namespace it's qualified with (or none at all) is an exact match ๐
The XPath 1.0 recommendation specifies "namespace-uri()" and
"local-name()" node-set functions that can be used within
predicates. These functions may be utilized during XPath
evaluations if there are no other means to "register" prefixes
with associated namespace URIs. They can also be used when
handling selections where default namespaces are attached to
elements. However, this specification does not allow the usage of
these functions.
4.2.3. Namespaces and Added/Changed Content โจ
Okay bestie, the elements inside the changed data content are also in scope of namespace declarations ๐. So if you add a brand-new namespace-qualified element to the target XML document, the diff document MUST contain a namespace declaration that applies to that element ๐ . The agent processing the diff document MUST also make sure the target document has that same declaration. Just like XPath, "same" here means the namespace URIs MUST be equal, but the prefixes MAY be different in the diff and target documents ๐ฆ.
Here's the vibe check ๐ง: say a new added <a:bar> element has a namespace declaration reference to xmlns:a='foo:' in the diff document, but the target document only has the single in-scope declaration xmlns:b='foo:' at the insertion point. Then the namespace reference MUST be changed so that a <b:bar> element will exist in the patched document. The same rule applies even if default namespaces were used in either or both documents. The namespace URIs decide which references (prefixes) are correct in the patched document ๐ธ.
When the new or changed content has elements that declare new namespaces (locally scoped), those declarations get copied over unaltered (prefix and everything) from the XML diff document to the target XML document ๐. Default namespace declarations can only be added this way, but prefixed namespace declarations MAY be added or removed with XPath namespace axis semantics shown later in this document (look Section 4.3.3) โจ.
Now the tricky one ๐ญ. It gets spicy when the target document has several namespace declarations in scope for the same namespace. A target document might declare several different prefixes for one namespace. Normally, the agent applying the diff document picks the appropriate prefix for adding new elements, but in this special (and honestly pretty rare) case there's more than one choice. These requirements make the behavior deterministic:
- If the diff document happens to use a prefix that is one of the prefixes declared for the same namespace in the evaluation context node of the target document, this prefix MUST be used in the resulting patched document. An empty evaluable prefix and an existing in-scope default namespace declaration means that the default namespace MUST be chosen. In other words, the expanded names are then equal within the diff and patched documents.
- In an
<add>operation, the evaluation context node is the parent element of the inserted node. For example, with a selectorsel='*/ bar'and without aposattribute directive (look Section 4.3), it is the<bar>element of the root document element. With modifications of elements, the evaluation context node is the parent element of the modified element, which in the previous example is the root document element.
- In an
- Secondly, the prefix (also empty) of the evaluation context node MUST be chosen if the namespace URIs are equal.
- Lastly, if the above two rules still don't apply, first all in-scope namespace prefixes of the evaluation context node are arranged alphabetically in ascending order. If a default namespace declaration exists, it is interpreted as the first entry in this list. The prefix from the list is then chosen that appears as the closest and just before the compared prefix if it were inserted into the list. If the compared prefix were to exist before the first prefix, the first prefix in the list MUST be selected (i.e., there's no default namespace).
- For example, if the list of in-scope prefixes in the target document is "x", "y" and the compared prefix in the diff document is "xx", then the "x" prefix MUST be chosen. If an "a" prefix were evaluated, the "x" prefix, the first entry, MUST be chosen. If there were also an in-scope default namespace declaration, an evaluable "a" prefix would then select the default declaration. Note that unprefixed attributes don't inherit the default namespace declaration. When adding qualified attributes, the default namespace declaration is then not on this matching list of prefixes (see Section 4.3.2).
Heads up ๐: these requirements might mean the resulting patched document ends up with unused and/or superfluous namespace declarations. That's fine, the resulting patched document MUST NOT be "cleaned up" so that these namespace declarations are removed. Don't go tidying them away!
Note: In practice, the agent constructing a diff document can usually freely select the appropriate prefixes for the namespace declarations, and it doesn't need to know or care about the actual prefixes in the target document unless there are overlapping declarations. In other words, the diff format content is typically independent of how the target document uses its namespace prefixes. However, it may be very useful to know where namespaces are declared in the target document. The most typical use case is that the agent generating a diff has both the previous (target) and new (patched) documents available, so namespace declarations are exactly known. Note also, that in a case where the target document is not exactly known, it is allowed to use locally scoped namespace declarations. The consequences of that are larger and less human-readable patched documents ๐.
4.3. <add> Element ๐
The <add> element represents the addition of some new content to the target XML document. For example, a new element can be appended into an existing element ๐ง.
The new data content exists as the child node(s) of the <add> element. When adding attributes and namespaces, the child node of the <add> element MUST be a single text node. Otherwise, the <add> element MAY contain any mixture of element, text, comment or processing instruction nodes, in any order. All children of the <add> element are then copied into a target XML document. The namespace mangling procedure described earlier applies to added elements, which includes all of their attribute, namespace and descendant nodes ๐.
The <add> element type has three attributes: sel, type, and pos ๐ฆ.
The value of the optional type attribute is only used when adding attributes and namespaces. In that case, the located target node MUST be an element into which the new attributes and namespace declarations are inserted. When the value of this type attribute equals "@attr", the string attr is the name of the actual attribute being added. The value of this new attr attribute is the text node content of the <add> element. The less frequently used prefixed (i.e., namespace-qualified) attributes can also be added. If the value of the type attribute equals "namespace::pref", then pref is the actual prefix string to be used for the namespace declaration in the patched document, and the text node content of the <add> element contains the corresponding namespace URI ๐.
Note: Thetypeattribute is thus also an XPath selector, but it only locates attributes and namespaces. The attribute axis"attribute"has an abbreviated form"@", unlike the"namespace"axis, which doesn't have an abbreviated form. Double colons"::"are used as an axis separator in XPath ๐ค.
The value of the optional pos attribute indicates the positioning of new data content. It is not used when adding attributes or namespaces. When neither the type nor the pos attribute exists, the children of the <add> element are appended as the last child node(s) of the located target element. When the value of the pos attribute is "prepend", the new node(s) are added as the first child node(s) of the located target element. With the value of "before", the added new node(s) MUST be the immediate preceding sibling node(s) of the located target node, and with "after", they are the immediate following sibling node(s) ๐ธ.
Some examples follow that show off these <add> attributes ๐
. The nodes aren't namespace qualified, so there are no prefixes here, and we're only showing the patch operation elements, not the whole XML diff content. Full examples are in Appendix A.
4.3.1. Adding an Element ๐ง
Here's an addition of an element:
<add sel="doc"><foo id="ert4773">This is a new child</foo></add>
Once the <doc> element has been found in the target XML document, a new <foo> element is appended as the last child node of the <doc> element. The located target node, the <doc> element, is naturally the root element of the target XML document. The new <foo> element has an id attribute and a child text node ๐.
4.3.2. Adding an Attribute ๐
Here's an addition of an attribute:
<add sel="doc/foo[@id='ert4773']" type="@user">Bob</add>
This operation adds a new user attribute to the <foo> element that was located using an id attribute value predicate. The value of this new user attribute is "Bob" ๐ซถ.
A similar patched XML document is achieved when using a validating XML parser, if the sel selector value had been id("ert4773") and if the data type of the id attribute is "ID" [W3C.REC-xmlschema-2-20041028] โจ.
Note that with namespace qualified attributes, the prefix matching rules within the type attribute are evaluated with similar rules to those described in Section 4.2.3. Also, the possible default namespace declaration of the context element isn't applicable in that case ๐.
Note: As theselselector value MAY contain quotation marks, escaped forms"""or"'"can be used within attribute values. However, it is often more appropriate to use the apostrophe (') character, as shown in these examples. An alternative is also to interchange the apostrophes and quotation marks ๐.
4.3.3. Adding a Prefixed Namespace Declaration ๐
Here's an addition of a prefixed namespace declaration:
<add sel="doc" type="namespace::pref">urn:ns:xxx</add>
This operation adds a new namespace declaration to the <doc> element. The prefix of this new namespace node is pref, and the namespace URI is "urn:ns:xxx" ๐ฆ.
4.3.4. Adding Node(s) with the 'pos' Attribute ๐
Here's an addition of a comment node:
<add
sel="doc/foo[@id='ert4773']" pos="before"><!-- comment --></add>
This operation adds a new comment node just before the <foo> element, as an immediate preceding sibling node. This is also an example of how a pos attribute directive can be used ๐ธ.
4.3.5. Adding Multiple Nodes โจ
Okay so, white space text nodes are where things get a little spicy ๐ถ๏ธ The XPath 1.0 data model says a text node MUST NOT have another text node as an immediate sibling node. Check this out:
<add sel="doc">
<foo id="ert4773">This is a new child</foo></add>
The <add> element then has two child nodes: a white space text node (a linefeed and two spaces) and a <foo> element. If the existing last child of the <doc> element is a text node, its content and the white space text node content MUST then be combined together. ๐ซถ Otherwise, (white space) text nodes can be added just like elements, so the canonical form of the patched XML document stays deterministic. Since several sibling nodes can go in with a single <add> operation, a "pretty printing" style is totally maintainable. ๐
Still another example about text nodes, because they are a lot ๐ญ
<add sel="*/foo/text()[2]" pos="after">new<bar/>elem</add>
First, the second text node child of the <foo> element gets located. The new content has two text nodes and an element. Since there cannot be immediate sibling text nodes, the located target text node content and the first new text node content MUST be combined together. Basically, if the 'pos' value had been "before", the second new text node content would get prepended to the located target text node instead. ๐ง
Note: It is still worth noting that text nodes MAY contain CDATA sections, and those aren't treated as separate nodes. Once these CDATA sections exist within the new text nodes, they SHOULD be moved unaltered to the patched XML document. ๐
XML entities [W3C.REC-xml-20060816] cannot be patched with this framework, bestie ๐ โโ๏ธ BUT references to anything other than predefined internal entities can still live inside text nodes or attributes, as long as the XML prolog has those declarations. Those references may then be preserved if both the XML diff and the target XML document have identical declarations in their prologs. Otherwise, references may be replaced with identical text, as long as the "canonically equivalent" rule is obeyed. Rules are rules, babe ๐
4.4. <replace> Element ๐ฆ
The <replace> element represents a replacement operation. Think: an existing element gets updated with a new element, or an attribute value gets swapped for a new value. A <replace> operation always updates a single node or node content at a time, so no multitasking here ๐
The <replace> element type only has a 'sel' attribute. If the located target node is an element, a comment, or a processing instruction, then the child of the <replace> element MUST also be of the same type. Otherwise, the <replace> element MUST have text content, or it MAY be empty when replacing an attribute value or a text node content. ๐ธ
4.4.1. Replacing an Element
Here's a replacement of an element:
<replace sel="doc/foo[@a='1']"><bar a="2"/></replace>
This updates the <foo> element that has an 'a' attribute with the value "1". The located target element gets replaced with the <bar> element. So all descendant nodes, namespace declarations, and attributes of the replaced <foo> element (if any existed) are gone. Bye bye ๐
4.4.2. Replacing an Attribute Value
Here's a replacement of an attribute value:
<replace sel="doc/@a">new value</replace>
This replaces the 'a' attribute content of the <doc> element with the value "new value". If the <replace> element is empty, the 'a' attribute MUST then remain in the patched XML document, looking like <doc a=""/>. โจ
4.4.3. Replacing a Namespace Declaration URI
Here's a replacement of a namespace URI:
<replace sel="doc/namespace::pref">urn:new:xxx</replace>
This replaces the URI value of the 'pref' prefixed namespace node with "urn:new:xxx". The parent node of the namespace declaration MUST be the <doc> element, otherwise an error occurs. ๐จ
4.4.4. Replacing a Comment Node
Here's a replacement of a comment node:
<replace sel="doc/comment()[1]"><!-- This is the new content
--></replace>
This replaces a comment node. The located target node is the first comment node child of the <doc> element. ๐ฌ
4.4.5. Replacing a Processing Instruction Node
Here's a replacement of a processing instruction node:
<replace sel='doc/processing-instruction("test")'><?test bar="foobar"
?></replace>
This replaces the processing instruction node "test" whose parent is the <doc> element. ๐ง
4.4.6. Replacing a Text Node
Here's a replacement of a text node:
<replace
sel="doc/foo/text()[1]">This is the new text content</replace>
This replaces the first text node child of the <foo> element. The positional constraint "[1]" isn't usually needed, because element content is rarely of mixed type [W3C.REC-xmlschema-1-20041028], where several text node siblings typically exist. ๐ค
If a text node is updated and the <replace> element is empty, the text node MUST thus be removed, since a text node MUST always have at least one character of data. No empty text nodes allowed, periodt ๐
4.5. <remove> Element ๐๏ธ
The <remove> element represents a removal operation of, for example, an existing element or an attribute.
The <remove> element type has two attributes: 'sel' and 'ws'. The value of the optional 'ws' attribute is used to remove the possible white space text nodes that exist either as immediate following or preceding sibling nodes of the located target node. The 'ws' attribute is only allowed when removing other types than text, attribute, and namespace nodes. If the value of 'ws' is "before", the purpose is to remove the immediate preceding sibling node, which MUST be a white space text node. If the value is "after", it's the corresponding following node. If the 'ws' value is "both", both the preceding and following white space text nodes MUST be removed. Main character energy ๐
4.5.1. Removing an Element
Here's a removal of an element, including all of its descendant, attribute, and namespace nodes:
<remove sel="doc/foo[@a='1']" ws="after"/>
This removes the <foo> element, as well as the immediate following sibling white space text node of the <foo> element. If the immediate following sibling node is not a white space text node, an error occurs. ๐
โโ๏ธ
4.5.2. Removing an Attribute
Here's a removal of an attribute node:
<remove sel="doc/@a"/>
This removes the 'a' attribute node from the <doc> element. ๐ซง
4.5.3. Removing a Prefixed Namespace Declaration
Here's a removal of a prefixed namespace node:
<remove sel="doc/foo/namespace::pref"/>
This removes the 'pref' prefixed namespace node from the <foo> element. Naturally, this prefix MUST NOT be associated with any node prior to the removal of this namespace node. Also, the parent node of this namespace declaration MUST be the <foo> element. ๐
4.5.4. Removing a Comment Node
Here's a removal of a comment node:
<remove sel="doc/comment()[1]"/>
This removes the first comment node child of the <doc> element. Gone, no cap ๐ซฅ
4.5.5. Removing a Processing Instruction Node
Here's a removal of a processing instruction node:
<remove sel='doc/processing-instruction("test")'/>
This removes the "test" processing instruction node child of the <doc> element. ๐
4.5.6. Removing a Text Node
Here's a removal of a text node:
<remove sel="doc/foo/text()[1]"/>
This removes the first text node child of the <foo> element. โ๏ธ
When removing an element, a comment, or a processing instruction node that has immediate preceding and following sibling text nodes, and there's no 'ws' directive, the content of those two text nodes MUST be combined together. The latter text node thus disappears from the document. Two become one, iykyk ๐ซถ
5. Error Handling ๐จ
It is an error condition if any of the patch operations cannot be unambiguously fulfilled. In other words, once a particular patch operation fails, it is an error condition, and processing further patch operations is hardly sensible. Like, if step one fell apart, why keep going? ๐
A new MIME error format is defined for applications that need deterministic error handling when patching cannot be applied. It is anticipated that these error elements can be used within other MIME types that allow extension elements. So the error stuff can travel with other formats too, which is honestly iconic of it ๐ฆโจ
5.1. Error Elements
okay so the root element of the error document is <patch-ops-error> ๐ and its content is one specific error condition. Every condition gets its own element, so each one can carry different info about what went wrong ๐ All error elements support a phrase attribute for text that's meant for a human to read ๐ซถ The optional xml:lang MAY be used to say what language the phrase is in ๐ Most of the error condition elements are supposed to hold the patch operation element that made the patch fail ๐งฉ
these are the error elements this spec defines ๐
<invalid-attribute-value>: the validity constraints onsel,type,ws, orposattribute values MAY be flagged with this one, aka the content isn't allowed ๐ โโ๏ธ It also works if an added or changed attribute's content isn't valid, like if CDATA sections got used when a brand new attribute was supposed to be added ๐<invalid-character-set>: the patch couldn't be applied because the diff and the patched document use different character sets ๐ค<invalid-diff-format>: the diff body of the request wasn't a well-formed XML document, or wasn't a valid one according to its schema ๐<invalid-entity-declaration>: an entity reference got found, but its declaration couldn't be located or resolved ๐ง<invalid-namespace-prefix>: the namespace URI for the given prefix couldn't be located or resolved. Like, a prefix got used insideselbut its declaration is missing from the target document ๐<invalid-namespace-uri>: the namespace URI value isn't valid, or the target document didn't have this declaration ๐ซ<invalid-node-types>: the node types in a<replace>operation didn't match. For example,selfinds an element but the replaceable content is text ๐ Also, a<replace>operation might find one unique element, but the replaceable content had multiple nodes ๐<invalid-patch-directive>: a patch directive couldn't be fulfilled because the given directives weren't understood ๐คทโโ๏ธ<invalid-root-element-operation>: the root element of the document can't be removed, and another sibling element for the document root element can't be added either ๐<invalid-xml-prolog-operation>: a patch failure related to XML prolog nodes ๐<invalid-whitespace-directive>: a<remove>operation needs to remove a white space node that doesn't exist in the target document ๐ซ<unlocated-node>: a single unique node (usually an element) couldn't be found with theselattribute value. Finding multiple nodes can also lead to this error ๐<unsupported-id-function>: the nodeset functionid()isn't supported, so attributes with the ID type aren't known ๐ชช<unsupported-xml-id>: thexml:idattribute as an ID attribute in XML documents isn't supported ๐ โโ๏ธ
extra error elements can be put inside the root <patch-ops-error> element from any namespace โจ The IETF MAY specify more error elements in the urn:ietf:params:xml:ns:patch-ops-error namespace ๐
here's an example ๐ this one says someone tried to add a new <note> element (with white space) into a document, but the parent element couldn't be found ๐ญ
<?xml version="1.0" encoding="UTF-8"?>
<patch-ops-error
xmlns:p="urn:ietf:params:xml:ns:pidf-diff"
xmlns="urn:ietf:params:xml:ns:patch-ops-error">
<unlocated-node
phrase="a unique node could not be located with the id() function."
><p:add sel='id("ert4773")'>
<p:note>some text added</p:note>
</p:add></unlocated-node>
</patch-ops-error>
6. Usage of Patch Operations ๐ฆ
okay this part is about how to actually use patch ops ๐ An XML diff document SHOULD only contain the nodes that got modified, because the whole point is to save bandwidth and storage ๐ง BUT if there's a huge pile of changes, it can be better to just send the full document content instead ๐ฆ How you'd do that in practice is out of scope for this doc, so that's on you bestie ๐ซถ
some applications MAY need the full versioning history to be indicated, even if the history has extra changes that aren't needed ๐ This framework doesn't force any specific behavior, so applications MAY decide the right semantics for themselves ๐ธ Also, in practice, applications are free to pick whatever algorithms they like when generating diff document content ๐ฅ
7. Usage of Selector Values ๐ง
it's up to the application to decide what kind of selector values to use ๐ Positional element selectors like "*/*[3]/*[2]" give you the shortest selectors, but you gotta be careful with them ๐ฌ When several sibling elements get removed, the positional indexes change after each update. The same thing happens when new elements get inserted into the tree ๐ Using names with possible attribute predicates, like doc[@sel='foo'], is usually easier for an application to deal with (an auto diff tool, for example), but it makes the diff documents bigger ๐
8. XML Schema Types of Patch Operation Elements ๐
here are the schema types for the patch operation elements ๐ง
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE schema [
<!ENTITY ncname "\i\c*">
<!ENTITY qname "(&ncname;:)?&ncname;">
<!ENTITY aname "@&qname;">
<!ENTITY pos "\[\d+\]">
<!ENTITY attr "\[&aname;='(.)*'\]|\[&aname;="(.)*"\]">
<!ENTITY valueq "\[(&qname;|\.)="(.)*"\]">
<!ENTITY value "\[(&qname;|\.)='(.)*'\]|&valueq;">
<!ENTITY cond "&attr;|&value;|&pos;">
<!ENTITY step "(&qname;|\*)(&cond;)*">
<!ENTITY piq "processing-instruction\(("&ncname;")\)">
<!ENTITY pi "processing-instruction\(('&ncname;')?\)|&piq;">
<!ENTITY id "id\(('&ncname;')?\)|id\(("&ncname;")?\)">
<!ENTITY com "comment\(\)">
<!ENTITY text "text\(\)">
<!ENTITY nspa "namespace::&ncname;">
<!ENTITY cnodes "(&text;(&pos;)?)|(&com;(&pos;)?)|((π)(&pos;)?)">
<!ENTITY child "&cnodes;|&step;">
<!ENTITY last "(&child;|&aname;|&nspa;)">
]>
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:simpleType name="xpath">
<xsd:restriction base="xsd:string">
<xsd:pattern
value="(/)?((&id;)((/&step;)*(/&last;))?|(&step;/)*(&last;))"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="xpath-add">
<xsd:restriction base="xsd:string">
<xsd:pattern
value="(/)?((&id;)((/&step;)*(/&child;))?|(&step;/)*(&child;))"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="pos">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="before"/>
<xsd:enumeration value="after"/>
<xsd:enumeration value="prepend"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="type">
<xsd:restriction base="xsd:string">
<xsd:pattern value="&aname;|&nspa;"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="add">
<xsd:complexContent mixed="true">
<xsd:restriction base="xsd:anyType">
<xsd:sequence>
<xsd:any processContents="lax" namespace="##any"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="sel" type="xpath-add"
use="required"/>
<xsd:attribute name="pos" type="pos"/>
<xsd:attribute name="type" type="type"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="replace">
<xsd:complexContent mixed="true">
<xsd:restriction base="xsd:anyType">
<xsd:sequence>
<xsd:any processContents="lax" namespace="##any"
minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="sel" type="xpath" use="required"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:simpleType name="ws">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="before"/>
<xsd:enumeration value="after"/>
<xsd:enumeration value="both"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="remove">
<xsd:attribute name="sel" type="xpath" use="required"/>
<xsd:attribute name="ws" type="ws"/>
</xsd:complexType>
</xsd:schema>
9. XML Schema of Patch Operation Errors ๐
and last but not least, the schema definitions for the patch operation errors ๐
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
targetNamespace="urn:ietf:params:xml:ns:patch-ops-error"
xmlns:tns="urn:ietf:params:xml:ns:patch-ops-error"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<!-- This import brings in the XML language attribute xml:lang-->
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
<!-- ROOT document element for signaling patch-ops errors -->
<xsd:element name="patch-ops-error">
<xsd:complexType>
<xsd:sequence>
<xsd:any namespace="##any" processContents="lax"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:anyAttribute processContents="lax"/>
</xsd:complexType>
</xsd:element>
<!-- patch-ops error elements:
not intended to be used as root documnet elements -->
<xsd:element name="invalid-attribute-value"
type="tns:patch-error"/>
<xsd:element name="invalid-character-set"
type="tns:patch-error-simple"/>
<xsd:element name="invalid-diff-format"
type="tns:patch-error-simple"/>
<xsd:element name="invalid-entity-declaration"
type="tns:patch-error"/>
<xsd:element name="invalid-namespace-prefix"
type="tns:patch-error"/>
<xsd:element name="invalid-namespace-uri"
type="tns:patch-error"/>
<xsd:element name="invalid-node-types"
type="tns:patch-error"/>
<xsd:element name="invalid-patch-directive"
type="tns:patch-error"/>
<xsd:element name="invalid-root-element-operation"
type="tns:patch-error"/>
<xsd:element name="invalid-xml-prolog-operation"
type="tns:patch-error"/>
<xsd:element name="invalid-whitespace-directive"
type="tns:patch-error"/>
<xsd:element name="unlocated-node"
type="tns:patch-error"/>
<xsd:element name="unsupported-id-function"
type="tns:patch-error"/>
<xsd:element name="unsupported-xml-id"
type="tns:patch-error"/>
<!-- simple patch-ops error type -->
<xsd:complexType name="patch-error-simple">
<xsd:attribute name="phrase" type="xsd:string"/>
<xsd:attribute ref="xml:lang"/>
<xsd:anyAttribute processContents="lax"/>
</xsd:complexType>
<!-- error type which includes patch operation -->
<xsd:complexType name="patch-error">
<xsd:sequence>
<xsd:any namespace="##any" processContents="lax"/>
</xsd:sequence>
<xsd:attribute name="phrase" type="xsd:string"/>
<xsd:attribute ref="xml:lang"/>
<xsd:anyAttribute processContents="lax"/>
</xsd:complexType>
</xsd:schema>
10. IANA Considerations ๐
okay bestie, IANA has to do some registry paperwork ๐ and here's everything they wrapped up:
- registered a new XML namespace URN according to the procedures of RFC 3688 [RFC3688].
- registered a new MIME type 'application/patch-ops-error+xml' according to the procedures of RFC 4288 [RFC4288] and guidelines in RFC 3023 [RFC3023].
- registered two XML Schemas according to the procedures of RFC 3688 [RFC3688].
10.1. URN Sub-Namespace Registration ๐
this spec registers a brand new XML namespace, following the guidelines in RFC 3688 [RFC3688]. the fields look like this:
URI: The URI for this namespace is
urn:ietf:params:xml:ns:patch-ops-error
Registrant Contact: IETF, SIMPLE working group, (simple@ietf.org),
Jari Urpalainen (jari.urpalainen@nokia.com).
and the XML page for the namespace is:
BEGIN
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type"
content="text/html;charset=iso-8859-1"/>
<title>Patch-Ops Error Namespace</title>
</head>
<body>
<h1>Namespace for Patch-Ops Error Documents</h1>
<h2>urn:ietf:params:xml:ns:patch-ops-error</h2>
<p>See <a
href="http://www.rfc-editor.org/rfc/rfc5261.txt">RFC5261</a>.</p>
</body>
</html>
END
10.2. application/patch-ops-error+xml MIME Type ๐
this is the MIME type for patch-ops errors, and the details are all right here:
MIME media type name: application
MIME subtype name: patch-ops-error+xml
Mandatory parameters: none
Optional parameters: Same as charset parameter application/xml as
specified in RFC 3023 [RFC3023].
Encoding considerations: Same as encoding considerations of
application/xml as specified in RFC 3023 [RFC3023].
Security considerations: See Section 10 of RFC 3023 [RFC3023].
Interoperability considerations: none.
Published specification: RFC 5261
Applications which use this media type: This document type has been
used to support transport of Patch-Ops errors in RFC 5261.
Additional Information:
Magic Number: None
File Extension: .xer
Macintosh file type code: "TEXT"
Personal and email address for further information: Jari
Urpalainen, jari.urpalainen@nokia.com
Intended usage: COMMON
Author/Change controller: The IETF
10.3. Patch-Ops-Types XML Schema Registration ๐
this section registers a new XML Schema, and its only content is the one shown in Section 8 โจ
URI:
urn:ietf:params:xml:schema:patch-ops
Registrant Contact:
IETF, SIMPLE working group, <simple@ietf.org>
Jari Urpalainen, <jari.urpalainen@nokia.com>
10.4. Patch-Ops-Error XML Schema Registration ๐ฆ
same energy here, but for the error schema. this section registers a new XML Schema, and its only content is the one shown in Section 9 ๐ซถ
URI:
urn:ietf:params:xml:schema:patch-ops-error
Registrant Contact:
IETF, SIMPLE working group, <simple@ietf.org>
Jari Urpalainen, <jari.urpalainen@nokia.com>
11. Security Considerations ๐
okay this part is SERIOUS bestie ๐ญ security depends SO much on the application using this framework. every app has its own needs, threat models, and security features, so you have to look at them one app at a time ๐
BUT this framework only uses a limited subset of XPath 1.0. apps might still be vulnerable to XPath injection attacks that can reveal some non-allowable content of an XML document. injection attacks are most likely with shareable resources, where a user can only see some specific parts of a resource. that's kinda the opposite of the usual use case for this framework ๐ to defend against those attacks, the input MUST be sanitized, and one way to do that is validating the diff formats with these restrictive schemas. no cap, do not skip this one ๐ฅ
12. Acknowledgments ๐ธ
the author wants to thank Lisa Dusseault for all her work, including BoF arrangements, comments, and editing help ๐ they also want to thank Eva Leppanen, Mikko Lonnfors, Aki Niemi, Jonathan Rosenberg, Miguel A. Garcia, Anat Angel, Stephane Bortzmeyer, Dave Crocker, Joel Halpern, Jeffrey Hutzelman, David Ward, and Chris Newman for their valuable comments, plus Ted Hardie for his input and support ๐ง
13. References ๐
13.1. Normative References ๐
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[W3C.REC-xml-20060816]
Maler, E., Paoli, J., Bray, T., Yergeau, F., and C.
Sperberg-McQueen, "Extensible Markup Language (XML) 1.0
(Fourth Edition)", World Wide Web Consortium
Recommendation REC-xml-20060816, August 2006,
<http://www.w3.org/TR/2006/REC-xml-20060816>.
[W3C.REC-xpath-19991116]
DeRose, S. and J. Clark, "XML Path Language (XPath)
Version 1.0", World Wide Web Consortium Recommendation
REC-xpath-19991116, November 1999,
<http://www.w3.org/TR/1999/REC-xpath-19991116>.
[W3C.REC-xml-names-20060816]
Hollander, D., Bray, T., Layman, A., and R. Tobin,
"Namespaces in XML 1.0 (Second Edition)", World Wide Web
Consortium Recommendation REC-xml-names-20060816, August
2006,
<http://www.w3.org/TR/2006/REC-xml-names-20060816>.
[W3C.REC-xmlschema-1-20041028]
Beech, D., Thompson, H., Maloney, M., and N. Mendelsohn,
"XML Schema Part 1: Structures Second Edition", World Wide
Web Consortium Recommendation REC-xmlschema-1-20041028,
October 2004,
<http://www.w3.org/TR/2004/REC-xmlschema-1-20041028>.
[W3C.REC-xml-c14n-20010315]
Boyer, J., "Canonical XML Version 1.0", World Wide Web
Consortium Recommendation REC-xml-c14n-20010315, March
2001,
<http://www.w3.org/TR/2001/REC-xml-c14n-20010315>.
[W3C.REC-xmlschema-2-20041028]
Malhotra, A. and P. Biron, "XML Schema Part 2: Datatypes
Second Edition", World Wide Web Consortium Recommendation
REC-xmlschema-2-20041028, October 2004,
<http://www.w3.org/TR/2004/REC-xmlschema-2-20041028>.
[W3C.WD-xml-id-20041109]
Veillard, D., Walsh, N., and J. Marsh, "xml:id Version
1.0", W3C LastCall WD-xml-id-20041109, November 2004.
[RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
10646", STD 63, RFC 3629, November 2003.
[RFC3023] Murata, M., St. Laurent, S., and D. Kohn, "XML Media
Types", RFC 3023, January 2001.
[RFC3688] Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688,
January 2004.
[RFC4288] Freed, N. and J. Klensin, "Media Type Specifications and
Registration Procedures", BCP 13, RFC 4288, December 2005.
13.2. Informative References ๐ง
[W3C.REC-xpath20-20070123]
Berglund, A., Fernandez, M., Chamberlin, D., Boag, S.,
Robie, J., Kay, M., and J. Simeon, "XML Path Language
(XPath) 2.0", World Wide Web Consortium Recommendation
REC-xpath20-20070123, January 2007,
<http://www.w3.org/TR/2007/REC-xpath20-20070123>.
[RFC4825] Rosenberg, J., "The Extensible Markup Language (XML)
Configuration Access Protocol (XCAP)", RFC 4825, May 2007.
[RFC3265] Roach, A., "Session Initiation Protocol (SIP)-Specific
Event Notification", RFC 3265, June 2002.
[RFC5262] Lonnfors, M., Leppanen, E., Khartabil, H., and J.
Urpalainen, "Presence Information Data format (PIDF)
Extension for Partial Presence", RFC 5262, September 2008.
[SIMPLE-XCAP]
Urpalainen, J. and J. Rosenberg, "An Extensible Markup
Language (XML) Document Format for Indicating A Change in
XML Configuration Access Protocol (XCAP) Resources", Work
in Progress, May 2008.
[RFC3903] Niemi, A., Ed., "Session Initiation Protocol (SIP)
Extension for Event State Publication", RFC 3903, October
2004.
Appendix A. Informative Examples ๐ง
all of these examples assume an imaginary XML diff document that includes these patch operation elements โจ
A.1. Adding an Element ๐ท
An example target XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
</doc>
An XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<add sel="doc"><foo id="ert4773">This is a new child</foo></add>
</diff>
A result XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
<foo id="ert4773">This is a new child</foo></doc>
A.2. Adding an Attribute ๐
An example target XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
<foo id="ert4773">This is a new child</foo></doc>
An XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<add sel="doc/foo[@id='ert4773']" type="@user">Bob</add>
</diff>
A result XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
<foo id="ert4773" user="Bob">This is a new child</foo></doc>
A.3. Adding a Prefixed Namespace Declaration ๐
An example target XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
<foo id="ert4773">This is a new child</foo></doc>
An XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<add sel="doc" type="namespace::pref">urn:ns:xxx</add>
</diff>
A result XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns:pref="urn:ns:xxx">
<note>This is a sample document</note>
<foo id="ert4773">This is a new child</foo></doc>
A.4. Adding a Comment Node with the 'pos' Attribute ๐
An example target XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
<foo id="ert4773">This is a new child</foo></doc>
An XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<add sel="doc/foo[@id='ert4773']" pos="before"><!-- comment --></add>
</diff>
A result XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
<!-- comment --><foo id="ert4773">This is a new child</foo></doc>
A.5. Adding Multiple Nodes ๐
An example target XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
</doc>
An XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<add sel="doc">
<foo id="ert4773">This is a new child</foo></add>
</diff>
A result XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<note>This is a sample document</note>
<foo id="ert4773">This is a new child</foo></doc>
A.6. Replacing an Element ๐ฆ
An example target XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
</doc>
An XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<replace sel="doc/foo[@a='1']"><bar a="2"/></replace>
</diff>
A result XML document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<bar a="2"/>
</doc>
A.7. Replacing an Attribute Value ๐
okay so the target doc has an attribute a="test" on its root, and the diff swaps that value out for something new ๐ฆ
Here's the target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc a="test">
<foo a="1">This is a sample document</foo>
</doc>
Here's the XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<replace sel="doc/@a">new value</replace>
</diff>
And here's the result document, where the root's a is now new value and the a on foo is untouched ๐ธ
<?xml version="1.0" encoding="UTF-8"?>
<doc a="new value">
<foo a="1">This is a sample document</foo>
</doc>
A.8. Replacing a Namespace Declaration URI ๐
the target doc has a prefixed namespace declaration, pref bound to urn:test, and the diff changes that URI to urn:new:xxx โจ
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns:pref="urn:test">
<foo a="1">This is a sample document</foo>
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<replace sel="doc/namespace::pref">urn:new:xxx</replace>
</diff>
The result document, with the pref declaration now pointing at urn:new:xxx ๐
<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns:pref="urn:new:xxx">
<foo a="1">This is a sample document</foo>
</doc>
A.9. Replacing a Comment Node ๐
we're swapping out a comment for a brand new one, and it's giving clean ๐ซถ
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns:pref="urn:test">
<foo a="1">This is a sample document</foo>
<!-- comment -->
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<replace sel="doc/comment()[1]"><!-- This is the new content
--></replace>
</diff>
The result document, where the comment is now the new content ๐ฆ
<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns:pref="urn:test">
<foo a="1">This is a sample document</foo>
<!-- This is the new content
-->
</doc>
A.10. Replacing a Processing Instruction Node ๐ง
same energy, but for a processing instruction ๐
the test one gets a fresh bar="foobar" โจ
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
<?test foo="bar"?>
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<replace sel='doc/processing-instruction("test")'
><?test bar="foobar"?></replace>
</diff>
The result document ๐
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
<?test bar="foobar"?>
</doc>
A.11. Replacing a Text Node ๐ธ
the text inside foo gets a glow-up, and the rest of the doc stays exactly as it was ๐ซถ
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<replace sel="doc/foo/text()[1]"
>This is the new text content</replace></diff>
The result document, with the new text sitting inside foo ๐
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is the new text content</foo>
</doc>
A.12. Removing an Element ๐๏ธ
bye bye foo ๐ the remove here uses ws="after", which is why the closing </doc> ends up sitting a bit funny in the result ๐
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<remove sel="doc/foo[@a='1']" ws="after"/>
</diff>
The result document ๐
<?xml version="1.0" encoding="UTF-8"?>
<doc>
</doc>
A.13. Removing an Attribute ๐
the root's a attribute is getting the boot, and foo keeps its own a="1" ๐
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc a="foo">
<foo a="1">This is a sample document</foo>
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<remove sel="doc/@a"/>
</diff>
The result document, where only the root's a is gone ๐ฆ
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
</doc>
A.14. Removing a Prefixed Namespace Declaration ๐
the pref namespace declaration sitting on foo gets removed, but the comment next to it survives ๐ซถ
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1" xmlns:pref="urn:test"
>This is a sample document</foo>
<!-- comment -->
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<remove sel="doc/foo/namespace::pref"/>
</diff>
The result document, with the declaration gone and the comment still hanging out ๐
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
<!-- comment -->
</doc>
A.15. Removing a Comment Node ๐
comment gone, โจ and this time ws="after" is doing its thing again, so the closing tag shifts ๐
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
<!-- comment -->
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<remove sel="doc/comment()[1]" ws="after"/>
</diff>
The result document ๐
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
</doc>
A.16. Removing a Processing Instruction Node ๐ง
the test processing instruction is out, and the rest of the doc is still slaying ๐
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
<?test?>
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<remove sel='doc/processing-instruction("test")'/>
</diff>
The result document โญ
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
</doc>
A.17. Removing a Text Node ๐
the text inside foo gets deleted, and foo is left as an empty element with its attribute still on it ๐ซถ
The target document:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1">This is a sample document</foo>
</doc>
The XML diff document:
<?xml version="1.0" encoding="UTF-8"?>
<diff>
<remove sel="doc/foo/text()[1]"/>
</diff>
The result document ๐ธ
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<foo a="1"/>
</doc>
A.18. Several Patches With Namespace Mangling ๐๐
okay this one is the boss level ๐ญ the target doc has a default namespace and a prefixed one, and the diff gets a bunch of patches in a row, so the prefixes get a little tangled
The target document, where namespace qualified elements exist:
<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns="urn:ietf:params:xml:ns:xxx"
xmlns:z="urn:ietf:params:xml:ns:yyy">
<note>This is a sample document</note>
<elem a="foo">
<child/>
</elem>
<elem a="bar">
<z:child/>
</elem>
</doc>
This is an imaginary XML diff document, where the prefix p stands for the targetNamespace of this imaginary schema ๐ฎ
<?xml version="1.0" encoding="UTF-8"?>
<p:diff xmlns="urn:ietf:params:xml:ns:xxx"
xmlns:y="urn:ietf:params:xml:ns:yyy"
xmlns:p="urn:ietf:params:xml:ns:diff">
<p:add sel="doc/elem[@a='foo']"> <!-- This is a new child -->
<child id="ert4773">
<y:node/>
</child>
</p:add>
<p:replace sel="doc/note/text()">Patched doc</p:replace>
<p:remove sel="*/elem[@a='bar']/y:child" ws="both"/>
<p:add sel="*/elem[@a='bar']" type="@b">new attr</p:add>
</p:diff>
Here's one possible form of the result document after all those patches get applied โจ
<?xml version="1.0" encoding="UTF-8"?>
<doc xmlns="urn:ietf:params:xml:ns:xxx"
xmlns:z="urn:ietf:params:xml:ns:yyy">
<note>Patched doc</note>
<elem a="foo">
<child/>
<!-- This is a new child -->
<child id="ert4773">
<z:node/>
</child>
</elem>
<elem a="bar" b="new attr"/>
</doc>
Now the tea ๐ซ the <node> element and the removed <child> element use prefixes in the XML diff document that are different from the "identical" namespace declarations in the target XML document. If the target had used a prefixed namespace declaration instead of the default one, the XML diff document could still have been the same. The added new qualified elements would just have inherited that prefix ๐ง๐
Author's Address ๐
Jari Urpalainen
Nokia
Itamerenkatu 11-13
Helsinki 00180
Finland
Phone: +358 7180 37686
EMail: jari.urpalainen@nokia.com
Full Copyright Statement ๐
Copyright (C) The IETF Trust (2008).
This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.
This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Intellectual Property ๐ฆ
The IETF takes no position on the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document, or on whether any license under such rights might or might not be available. It also doesn't represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat, any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org. ๐
โจ
๐ฆ where this page comes from
- ietf: rfc5261 2008-09
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms