4Suite contains an implementation of XUpdate, the XML Update Language. XUpdate is essentially an XPath-based XML transformation language, like XSLT. An XUpdate document is an XML document that specifies what changes should be made to another XML document.
XUpdate is neither a W3C Recommendation nor an ISO or IETF standard. It is just a project of the XML:DB Initiative's XUpdate Working Group, and it never advanced beyond a Working Draft published in September, 2000. It is not very well specified, but it is fairly convenient and enables a basic level of functionality, so it has enjoyed popularity in a number of implementations.
4Suite's XUpdate implementation, 4XUpdate, consists of a Python API (via the Ft.Xml.XUpdate module) and a command-line script (4xupdate). The APIs involve taking a source document (the XML to be updated) and an XUpdate document (the changes to apply), and either producing a new document or updating the source document in-place.
The Python API can be invoked directly on Domlette objects or on InputSources. Here is an example of using the ApplyXUpdate convenience function, which takes InputSources:
from Ft.Xml.Domlette import PrettyPrint
from Ft.Xml.InputSource import DefaultFactory
try:
from Ft.Xml.XUpdate import ApplyXUpdate
except ImportError:
# the function name changed between 1.0a3 and 1.0b1
from Ft.Xml.XUpdate import ApplyXupdate as ApplyXUpdate
SOURCE='''<?xml version = "1.0"?>
<ADDRBOOK xmlns="http://bogus/">
<ENTRY ID="fr">
<NAME>fred</NAME>
</ENTRY>
</ADDRBOOK>'''
XU='''<?xml version="1.0"?>
<xu:modifications version="1.0" xmlns:xu="http://www.xmldb.org/xupdate"
xmlns:myns="http://bogus/">
<xu:append select="/myns:ADDRBOOK" child="last()">
<ENTRY ID="vz">
<NAME>Vasia Zhugenev</NAME>
</ENTRY>
</xu:append>
</xu:modifications>'''
src_isrc = DefaultFactory.fromString(SOURCE, "http://test1/")
xup_isrc = DefaultFactory.fromString(XU, "http://test2/")
result_dom = ApplyXUpdate(src_isrc, xup_isrc)
PrettyPrint(result_dom)
#expected:
#<?xml version="1.0" encoding="UTF-8"?>
#<ADDRBOOK xmlns="http://bogus/">
# <ENTRY ID="fr">
# <NAME>fred</NAME>
# </ENTRY>
#<ENTRY ID="vz">
# <NAME>Vasia Zhugenev</NAME>
# </ENTRY>
#</ADDRBOOK>
If you have both the source document and XUpdate document as Domlette nodes already, you can use the XUpdate processor directly:
# add to the above script... from Ft.Xml.Domlette import NonvalidatingReader from Ft.Xml.XUpdate import Processor src_isrc = DefaultFactory.fromString(SOURCE, "http://test1/") xup_isrc = DefaultFactory.fromString(XU, "http://test2/") src_dom = NonvalidatingReader.parse(src_isrc) xup_dom = NonvalidatingReader.parse(xup_isrc) proc = Processor() proc.execute(src_dom, xup_dom) # src_dom has been modified in-place PrettyPrint(src_dom)
Using the processor directly allows you to set XPath variables, if needed:
from Ft.Xml import EMPTY_NAMESPACE
# execute with $x='foo'
proc.execute(src_dom, xup_dom, {(EMPTY_NAMESPACE, u'x'): u'foo'})
The command-line script works on local files or even URIs, if resolvable, and normally sends the result XML to standard output, although it can also be made to write to a file. See "4xupdate -h" for usage instructions.
All of XUpdate (such as it's spec'ed) is currently implemented.
