{ "info": { "author": "Paul Everitt, Laurence Rowe and Martin Aspeli.", "author_email": "laurence@lrowe.co.uk", "bugtrack_url": null, "classifiers": [], "description": "=============================\nXDV - XSLT Deliverance Engine\n=============================\n\n.. contents:: Contents\n\nIntroduction\n============\n\nXDV is an implementation of the `Deliverance`_ concept using pure XSLT. In\nshort, it is a way to apply a style/theme contained in a static HTML web page\n(usually with related CSS, JavaScript and image resources) to a dynamic\nwebsite created using any server-side technology.\n\nConsider a scenario where you have a dynamic website, to which you want to\napply a theme built by a web designer. The web designer is not familiar with\nthe technology behind the dynamic website, and so has supplied a \"static HTML\"\nversion of the site. This consists of an HTML file with more-or-less semantic\nmarkup, one or more style sheets, and perhaps some other resources like\nimages or JavaScript files.\n\nUsing XDV, you could apply this theme to your dynamic website as follows:\n\n1. Identify the placeholders in the theme file that need to be replaced with\n dynamic elements. Ideally, these should be clearly identifiable, for\n example with a unique HTML ``id`` attribute.\n2. Identify the corresponding markup in the dynamic website. Then write a\n \"replace\" or \"copy\" rule using XDV's rules syntax that replaces the theme's\n static placeholder with the dynamic content.\n3. Identify markup in the dynamic website that should be copied wholesale into\n the theme. CSS and JavaScript links in the ```` are often treated\n this way. Write an XDV \"append\" or \"prepend\" rule to copy these elements\n over.\n4. Identify parts of the theme and/or dynamic website that are superfluous.\n Write an XDV \"drop\" rule to remove these elements.\n\nThe rules file is written using a simple XML syntax. Elements in the theme\nand \"content\" (the dynamic website) can be identified using CSS3 or XPath\nselectors.\n\nOnce you have a theme HTML file and a rules XML file, you compile these using\nthe XDV compiler into a single XSLT file. You can then deploy this XSLT file\nwith your application. An XSLT processor (such as mod_transform in Apache)\nwill then transform the dynamic content from your website into the themed\ncontent your end users see. The transformation takes place on-the-fly for\neach request.\n\nBear in mind that:\n\n* You never have to write, or even read, a line of XSLT (unless you want to).\n* The XSLT transformation that takes place for each request is very fast.\n* Static theme resources (like images, stylesheets or JavaScript files) can\n be served from a static webserver, which is normally much faster than\n serving them from a dynamic application.\n* You can leave the original theme HTML untouched, with makes it easier to\n re-use for other scenarios. For example, you can stitch two unrelated\n applications together by using a single theme file with separate rules\n files. This would result in two compiled XSLT files. You could use location\n match rules or similar techniques to choose which one to invoke for a given\n request.\n\nWe will illustrate how to set up XDV for deployment below.\n\nInstallation\n============\n\nTo install XDV, you should install the ``xdv`` egg. You can do that using\n``easy_install``, ``pip`` or ``zc.buildout``. For example, using\n``easy_install`` (ideally in a ``virtualenv``)::\n \n $ easy_install -U xdv\n\nIf using ``zc.buildout``, you can use the following ``buildout.cfg`` as a\nstarting point. This will ensure that the console scripts are installed,\nwhich is important if you need to execute the XDV compiler manually::\n\n [buildout]\n parts =\n xdv\n\n [xdv]\n recipe = zc.recipe.egg\n eggs = xdv\n\nNote that ``lxml`` is a dependency of ``xdv``, so you may need to install the\nlibxml2 and libxslt development packages in order for it to build. On\nDebian/Ubuntu you can run::\n\n $ sudo apt-get install libxslt1-dev\n\nOn some operating systems, notably Mac OS X, installing a \"good\" ``lxml`` egg\ncan be problematic, due to a mismatch in the operating system versions of the\n``libxml2`` and ``libxslt`` libraries that ``lxml`` uses. To get around that,\nyou can compile a static ``lxml`` egg using the following buildout recipe::\n\n [buildout]\n # lxml should be first in the parts list\n parts =\n lxml\n xdv\n \n [lxml]\n recipe = z3c.recipe.staticlxml\n egg = lxml\n libxml2-url = http://xmlsoft.org/sources/libxml2-2.7.6.tar.gz\n libxslt-url = http://xmlsoft.org/sources/libxslt-1.1.26.tar.gz\n \n [xdv]\n recipe = zc.recipe.egg\n eggs = xdv\n\nOnce installed, you should find ``xdvcompiler`` and ``xdvrun`` in your\n``bin`` directory.\n\nRules file syntax\n=================\n\nThe rules file, conventionally called ``rules.xml``, is rooted in a tag\ncalled ````::\n\n \n \n \n ...\n \n \n\nHere we have defined two namespaces: the default namespace is used for rules\nand XPath selectors. The ``css`` namespace is used for CSS3 selectors. These\nare functionally equivalent. In fact, CSS selectors are replaced by the\nequivalent XPath selector during the pre-processing step of the compiler.\nThus, they have no performance impact.\n\nXDV supports complex CSS3 and XPath selectors, including things like the\n``nth-child`` pseudo-selector. You are advised to consult a good reference\nif you are new to XPath and/or CSS3.\n\nThe following elements are allowed inside the ```` element:\n\n````\n---------------\n\nUsed to replace an element in the theme entirely with an element in the\ncontent. For example::\n\n \n\nThe (near-)equivalent using CSS selectors would be::\n\n \n\nThe result of either is that the ```` element in the theme is\nreplaced with the ``<title />`` element in the (dynamic) content.\n\n``<copy />``\n------------\n\nUsed to replace the contents of a placeholder tag with a tag from the\ntheme. For example::\n\n <copy css:theme=\"#main\" css:content=\"#portal-content > *\" />\n\nThis would replace any placeholder content inside the element with id\n``main`` in the theme with all children of the element with id\n``portal-content`` in the content. The usual reason for using ``<copy />``\ninstead of ``<replace />``, is that the theme has CSS styles or other\nbehaviour attached to the target element (with id ``main`` in this case).\n\n``<append />`` and ``<prepend />``\n----------------------------------\n\nUsed to copy elements from the content into an element in the theme,\nleaving existing content in place. ``<append />`` places the matched\ncontent directly before the closing tag in the theme; ``<prepend />`` places\nit directly after the opening tag. For example::\n\n <append theme=\"/html/head\" content=\"/html/head/link\" />\n\nThis will copy all ``<link />`` elements in the head of the content into\nthe theme.\n\nAs a special case, you can copy individual *attributes* from a content\nelement to an element in the theme using ``<prepend />``::\n\n <prepend theme=\"/html/body\" content=\"/html/body/@class\" />\n\nThis would copy the ``class`` attribute of the ``<body />`` element in\nthe content into the theme (replacing an existing attribute with the\nsame name if there is one).\n\n``<before />`` and ``<after />``\n--------------------------------\n\nThese are equivalent to ``<append />`` and ``<prepend />``, but place\nthe matched content before or after the matched theme element, rather\nthan immediately inside it. For example:\n \n <before css:theme=\"#content\" css:content=\"#info-box\" />\n\nThis would place the element with id ``info-box`` from the content\nimmediately before the element with id ``content`` in the theme. If we\nwanted the box below the content instead, we could do::\n\n <after css:theme=\"#content\" css:content=\"#info-box\" />\n\n``<drop />``\n------------\n\nUsed to drop elements from the theme or the content. This is the only\nelement that accepts either ``theme`` or ``content`` attributes (or their\n``css:`` equivalents), but not both::\n\n <drop css:content=\"#portal-content .about-box\" />\n <copy css:theme=\"#content\" css:content=\"#portal-content > *\" />\n\nThis would copy all children of the element with id ``portal-content`` in\nthe theme into the element with id ``content`` in the theme, but only\nafter removing any element with class ``about-box`` inside the content\nelement first. Similarly::\n\n <drop theme=\"/html/head/base\" />\n\nWould drop the ``<base />`` tag from the head of the theme.\n\nOrder of rule execution\n-----------------------\n\nIn most cases, you should not care too much about the inner workings of the\nXDV compiler. However, it can sometimes be useful to understand the order\nin which rules are applied.\n\n1. ``<before />`` rules are always executed first.\n2. ``<drop />`` rules are executed next.\n3. ``<replace />`` rules are executed next, provided no ``<drop />`` rule was\n applied to the same theme node.\n4. ``<prepend />``, ``<copy />`` and ``<append />`` rules execute next,\n provided no ``<replace />`` rule was applied to the same theme node.\n5. ``<after />`` rules are executed last.\n\nBehaviour if theme or content is not matched\n--------------------------------------------\n\nIf a rule does not match the theme (whether or not it matches the content),\nit is silently ignored.\n\nIf a ``<replace />`` rule matches the theme, but not the content, the matched\nelement will be dropped in the theme::\n\n <replace css:theme=\"#header\" content=\"#header-element\" />\n\nHere, if the element with id ``header-element`` is not found in the content,\nthe placeholder with id ``header`` in the theme is removed.\n\nSimilarly, the contents of a theme node matched with a ``<copy />`` rule will\nbe dropped if there is no matching content. Another way to think of this is\nthat if no content node is matched, XDV uses an empty nodeset when copying or\nreplacing.\n\nIf you want the placeholder to stay put in the case of a missing content node,\nyou can make this a conditional rule::\n\n <replace css:theme=\"#header\" content=\"#header-element\" if-content=\"\" />\n\nSee below for more details on conditional rules.\n\nAdvanced usage\n--------------\n\nThe simple rules above should suffice for most use cases. However, there are\na few more advanced tools at your disposal, should you need them.\n\nConditional rules\n~~~~~~~~~~~~~~~~~\n\nSometimes, it is useful to apply a rule only if a given element appears or\ndoes not appear in the markup. The ``if-content`` attribute can be used with\nany rule to make it conditional.\n\n``if-content`` should be set an XPath expression. You can also use\n``css:if-content`` with a CSS3 expression. If the expression matches a node\nin the content, the rule will be applied::\n\n <copy css:theme=\"#portlets\" css:content=\".portlet\"/>\n <drop css:theme=\"#portlet-wrapper\" if-content=\"not(//*[@class='portlet'])\"/>\n\nThis will copy all elements with class ``portlet`` into the ``portlets``\nelement. If there are no matching elements in the content we drop the\n``portlet-wrapper`` element, which is presumably superfluous.\n\nHere is another example using CSS selectors::\n\n <copy css:theme=\"#header\" css:content=\"#header-box > *\" \n css:if-content=\"#personal-bar\"/>\n\nThis will copy the children of the element with id ``header-box`` in the\ncontent into the element with id ``header`` in the theme, so long as an\nelement with id ``personal-bar`` also appears somewhere in the content.\n\nAbove, we also saw the special case of an empty ``if-content`` (which also\nworks with an empty ``css:if-content``). This is a shortcut that means \"use\nthe expression in the ``content`` or ``css:content``` attribute as the\ncondition\". Hence the following two rules are equivalent::\n\n <copy css:theme=\"#header\" css:content=\"#header-box > *\"\n css:if-content=\"#header-box > *\"/>\n <copy css:theme=\"#header\" css:content=\"#header-box > *\" \n css:if-content=\"\"/>\n\nIf multiple rules of the same type match the same theme node but have\ndifferent ``if-content`` expressions, they will be combined as an\nif..else if...else block::\n\n <copy theme=\"/html/body/h1\" content=\"/html/body/h1/text()\"\n if-content=\"/html/body/h1\"/>\n <copy theme=\"/html/body/h1\" content=\"//h1[@id='first-heading']/text()\"\n if-content=\"//h1[@id='first-heading']\"/>\n <copy theme=\"/html/body/h1\" content=\"/html/head/title/text()\" />\n\nThese rules all attempt to fill the text in the ``<h1 />`` inside the body.\nThe first rule looks for a similar ``<h1 />`` tag and uses its text. If that\ndoesn't match, the second rule looks for any ``<h1 />`` with id\n``first-heading``, and uses its text. If that doesn't match either, the\nfinal rule will be used as a fallback (since it has no ``if-content``),\ntaking the contents of the ``<title />`` tag in the head of the content\ndocument.\n\nIncluding external content\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nNormally, the ``content`` attribute of any rule selects nodes from the\nresponse being returned by the underlying dynamic web server. However, it is\npossible to include content from a different URL using the ``href`` attribute\non any rule (other than ``<drop />``). For example::\n\n <append css:theme=\"#left-column\" css:content=\"#portlet\" href=\"/extra.html\"/>\n\nThis will resolve the URL ``/extra.html``, look for an element with id\n``portlet`` and then append to to the element with id ``left-column`` in the\ntheme.\n\nThe inclusion can happen in one of three ways:\n\n* Using the XSLT ``document()`` function. This is the default, but it can\n be explicitly specified by adding an attribute ``method=\"document\"`` to the \n rule element. Whether this is able to resolve the URL depends on how and\n where the compiled XSLT is being executed::\n \n <append css:theme=\"#left-column\" css:content=\"#portlet\"\n href=\"/extra.html\" method=\"document\" />\n \n* Via a Server Side Include directive. This can be specified by setting the\n ``method`` attribute to ``ssi``::\n \n <append css:theme=\"#left-column\" css:content=\"#portlet\"\n href=\"/extra.html\" method=\"ssi\"/>\n\n The output will look something like this::\n \n <!--# include wait=\"yes\" virtual=\"/extra.html?;filter_xpath=//*[@id%20=%20'portlet']\" -->\n \n This SSI instruction would need to be processed by a fronting web server\n such as Apache or nginx. Also note the ``;filter_xpath`` query string\n parameter. Since we are deferring resolution of the referenced document\n until SSI processing takes place (i.e. after the compiled XDV XSLT transform\n has executed), we need to ask the SSI processor to filter out elements in\n the included file that we are not interested in. This requires specific\n configuration. An example for nginx is included below.\n \n For simple SSI includes of a whole document, you may omit the ``content``\n selector from the rule::\n \n <append css:theme=\"#left-column\" href=\"/extra.html\" method=\"ssi\"/>\n \n The output then renders like this::\n \n <!--# include wait=\"yes\" virtual=\"/extra.html\" -->\n\n* Via an Edge Side Includes directive. This can be specified by setting the\n ``method`` attribute to ``esi``::\n \n <append css:theme=\"#left-column\" css:content=\"#portlet\"\n href=\"/extra.html\" method=\"esi\"/>\n\n The output is similar to that for the SSI mode::\n\n <esi:include src=\"/extra.html?;filter_xpath=//*[@id%20=%20'portlet']\"></esi:include>\n \n Again, the directive would need to be processed by a fronting server, such\n as Varnish. Chances are an ESI-aware cache server would not support\n arbitrary XPath filtering. If the referenced file is served by a dynamic\n web server, it may be able to inspect the ``;filter_xpath`` parameter and\n return a tailored response. Otherwise, if a server that can be made aware\n of this is placed in-between the cache server and the underlying web server,\n that server can perform the necessary filtering.\n\n For simple ESI includes of a whole document, you may omit the ``content``\n selector from the rule::\n \n <append css:theme=\"#left-column\" href=\"/extra.html\" method=\"esi\"/>\n \n The output then renders like this::\n \n <esi:include src=\"/extra.html\"></esi:include>\n\nModifying the theme on the fly\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSometimes, the theme is almost perfect, but cannot be modified, for example\nbecause it is being served from a remote location that you do not have access\nto, or because it is shared with other applications.\n\nXDV allows you to modify the theme using \"inline\" markup in the rules file.\nYou can think of this as a rule where the matched ``content`` is explicitly\nstated in the rules file, rather than pulled from the response being styled.\n\nFor example::\n\n <xdv:rules\n xmlns:xdv=\"http://namespaces.plone.org/xdv\"\n xmlns:css=\"http://namespaces.plone.org/xdv+css\"\n xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n >\n\n <xdv:append theme=\"/html/head\">\n <style type=\"text/css\">\n /* From the rules */\n body > h1 { color: red; }\n </style>\n </xdv:append>\n\n </xdv:rules>\n\nNotice how we have placed the rules in an explicit ``xdv`` namespace, so that\nwe can write the \"inline\" HTML without a namespace prefix.\n\nIn the example above, the ``<append />`` rule will copy the ``<style />``\nattribute and its contents into the ``<head />`` of the theme. Similar rules\ncan be constructed for ``<copy />``, ``<replace />``, ``<prepend />``, \n``<before />`` or ``<after />``.\n\nIt is even possible to insert XSLT instructions into the compiled theme in\nthis manner. Having declared the ``xsl`` namespace as shown above, we can do\nsomething like this::\n\n <xdv:replace css:theme=\"#details\">\n <dl id=\"details\">\n <xsl:for-each css:select=\"table#details > tr\">\n <dt><xsl:copy-of select=\"td[1]/text()\"/></dt>\n <dd><xsl:copy-of select=\"td[2]/node()\"/></dd>\n </xsl:for-each>\n </dl>\n </xdv:replace>\n\nNote that css expressions are converted to \"placeless\" XPath expressions,\nso ``css:select=\"table#details > tr\"`` converts to\n``select=\"//table[@id='details]/tr\"``. This means it would not be possible to\nuse ``css:select=\"td:first-child > *\"`` as you want a relative selector here.\nYou can, of course, just use a manual XPath in a ``select`` attribute instead.\n\nInline XSL directives\n~~~~~~~~~~~~~~~~~~~~~\n\nYou may supply inline XSL directives in the rules to tweak the final output,\nfor instance to strip space from the output document use::\n\n <rules xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n\n <xsl:strip-space elements=\"*\" />\n\n </rules>\n\nNote: this may effect the rendering of the page on the browser.\n\nTo use a strict doctype::\n\n <xsl:output\n doctype-public=\"-//W3C//DTD XHTML 1.0 Strict//EN\"\n doctype-system=\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"/>\n\nXInclude\n~~~~~~~~\n\nYou may wish to re-use elements of your rules file across multiple themes.\nThis is particularly useful if you have multiple variations on the same theme\nused to style different pages on a particular website.\n\nRules files may be included using the XInclude protocol.\n\nInclusions use standard XInclude syntax. For example::\n\n <rules\n xmlns=\"http://namespaces.plone.org/xdv\"\n xmlns:css=\"http://namespaces.plone.org/xdv+css\"\n xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n \n <xi:include href=\"standard-rules.xml\" />\n \n </rules>\n\nCompilation\n===========\n\nOnce you have written your rules file, you need to compile it to an XSLT for\ndeployment. In some cases, you may have an application server that does this\non the fly, e.g. if you are using the ``collective.xdv`` package with Plone.\nFor deployment to a web server like Apache or nginx, however, you will need\nto perform this step manually.\n\nThe easiest way to invoke the XDV compiler is via the ``xdvcompiler`` command\nline script which is installed with the ``xdv`` egg. To see its help output,\ndo::\n\n $ bin/xdvcompiler --help\n\nTo run the compiler with ``rules.xml`` operating on ``theme.html``::\n\n $ bin/xdvcompiler rules.xml theme.html\n\nThis will print the compiled XSLT file to the standard output. You can save\nit to a file instead using::\n\n $ bin/xdvcompiler -o theme.xsl rules.xml theme.html\n\nThe following command line options are available:\n\n* Use ``-p`` to pretty-print the output for improved readability. There is a\n risk that this could alter rendering in the browser, though, as browsers\n are sensitive to some kinds of whitespace.\n* Use ``-a`` to set an absolute prefix - see below.\n* Use ``-i`` to set the default external file inclusion mode to one of\n ``document``, ``ssi`` or ``esi``.\n* Use ``--trace`` to output trace logging during the compilation step. This\n can be helpful in debugging rules.\n\nCheck the output of the ``--help`` option for more details.\n\nAbsolute prefix\n---------------\n\nThe compiler can be passed an \"absolute prefix\". This is a string that will be\nprefixed to any *relative* URL referenced an image, link or stylesheet in the\ntheme HTML file, before the theme is passed to the compiler. This allows a\ntheme to be written so that it can be opened and views standalone on the\nfilesystem, even if at runtime its static resources are going to be served\nfrom some other location.\n\nFor example, say the theme is written with relative URLs for images and\nexternal resources, such as ``<img src=\"images/foo.jpg\" />``. When the\ncompiled theme is applied to a live site, this is unlikely to work for\nany URL other than a sibling of the ``images`` folder.\n\nLet's say the theme's static resources are served from a simple web server\nand made available under the directory ``/static``. In this case, we can\nset an absolute prefix of ``/static``. This will modify the ``<img />`` tag\nin the compiled theme so that it becomes an absolute path that will work for\nany URL: ``<img src=\"/static/images/foo.jpg\"`` />\n\nTesting the compiled theme\n--------------------------\n\nTo test the compiled theme, you can apply it to a static file representing\nthe content. The easiest way to do this is via the ``xdvrun`` script::\n\n $ bin/xdvrun theme.xsl content.html\n\nThis will print the output to the standard output. You can save it to a file\ninstead with::\n\n $ bin/xdvrun -o output.html theme.xsl content.html\n\nFor testing, you can also compile and run the theme in one go, by using the\n``-r`` (rules) and ``-t`` (theme) arguments to ``xdvrun``::\n\n $ bin/xdvrun -o output.html -r rules.xml -t theme.html content.html\n\nTo see the built-in help for this command, run::\n \n $ bin/xdvrun --help\n\nCompiling the theme in Python code\n----------------------------------\n\nYou can run the XDV compiler from Python code using the following helper\nfunction::\n\n >>> from xdv.compiler import compile_theme\n\nThis method takes the following arguments:\n\n* ``rules`` is the rules file, given either as a file name or a string with\n the file contents.\n* ``theme`` is the theme file, given either as a file name or a string with\n the file contents\n* ``extra`` is an optional XSLT file with XDV extensions, given as a URI\n (depracated, use inline xsl in the rules instead)\n* ``css`` can be set to False to disable CSS syntax support (providing a\n moderate speed gain)\n* ``xinclude`` can be set to ``False`` to enable XInclude support (at a\n moderate speed cost). If enabled, XInclude syntax can be used to split the\n rules file into multiple, re-usable fragments.\n* ``absolute_prefix`` can be set an string to be used as the \"absolute prefix\"\n for relative URLs - see above.\n* ``update`` can be set to ``False`` to disable the automatic update support\n for the old Deliverance 0.2 namespace (for a moderate speed gain)\n* ``trace`` can be set to True to enable compiler trace information\n* ``includemode`` can be set to 'document', 'esi' or 'ssi' to change the way\n in which includes are processed\n* ``parser`` can be set to an lxml parser instance; the default is an\n HTMLParser\n* ``compiler_parser``` can be set to an lxml parser instance; the default is a\n XMLParser\n* ``rules_parser`` can be set to an lxml parser instance; the default is a\n XMLParse.\n\nThe parser parameters may be used to add custom resolvers for external content\nif required. See the `lxml <http://codespeak.net/lxml>`_ documentation for\ndetails.\n\n``compile_theme()`` returns an XSLT document in ``lxml``'s ``ElementTree``\nformat. To set up a transform representing the theme and rules, you can do::\n\n from lxml import etree\n from xdv.compiler import compile_theme\n \n absolute_prefix = \"/static\"\n \n rules = \"rules.xml\"\n theme = \"theme.html\"\n \n compiled_theme = compile_theme(rules, theme,\n absolute_prefix=absolute_prefix)\n \n transform = etree.XSLT(compiled_theme)\n \nYou can now use this transformation::\n\n content = etree.parse(some_content)\n transformed = transform(content)\n \n output = etree.tostring(transformed)\n\nPlease see the ``lxml`` documentation for more details.\n\nDeployment\n==========\n\nBefore it can be used, the deployed theme needs to be deployed to a proxying\nweb server which can apply the XSLT to the response coming back from another\nweb application.\n\nIn theory, any XSLT processor will do. In practice, however, most websites\ndo not produce 100% well-formed XML (i.e. they do not conform to the XHTML\n\"strict\" doctype). For this reason, it is normally necessary to use an XSLT\nprocessor that will parse the content using a more lenient parser with some\nknowledge of HTML. libxml2, the most popular XML processing library on Linux\nand similar operating systems, contains such a parser.\n\nPlone\n-----\n\nIf you are working with Plone, the easiest way to use XDV is via the\n`collective.xdv <http://pypi.python.org/pypi/collective.xdv>`_ add-on. This\nprovides a control panel for configuring the XDV rules file, theme and\nother options, and hooks into a transformation chain that executes after\nPlone has rendered the final page to apply the XDV transform.\n\nEven if you intend to deploy the compiled theme to another web server,\n``collective.xdv`` is a useful development tool: so long as Zope is in\n\"development mode\", it will re-compile the theme on the fly, allowing you\nto make changes to theme and rules on the fly. It also provides some tools\nfor packaging up your theme and deploying it to different sites.\n\nWSGI\n----\n\nIf you are using a WSGI stack, you can use the `dv.xdvserver\n<http://pypi.python.org/pypi/dv.xdvserver>`_ middleware to apply an XDV\ntheme. This supports all the core XDV options, and can be configured to\neither re-compile the theme on the fly (useful for development), or compile\nit only once (useful for deployment.)\n\nIt is also possible to use this with the Paste ``proxy`` middleware to\ncreate a standalone XDV proxy for any site. See the `dv.xdvserver`_\ndocumentation for details.\n\nnginx\n-----\n\nTo deploy an XDV theme to the `nginx <http://nginx.org>`_ web server, you\nwill need to compile nginx with a special version of the XSLT module that\ncan (optionally) use the HTML parser from libxml2.\n\nIn the future, the necessary patches to enable HTML mode parsing will\nhopefully be part of the standard nginx distribution. In the meantime,\nthey are maintained in the `html-xslt <http://code.google.com/p/html-xslt/>`_\nproject.\n\nUsing a properly patched nginx, you can configure it with XSLT support like\nso::\n\n $ ./configure --with-http_xslt_module\n\nIf you are using zc.buildout and would like to build nginx, you can start\nwith the following example::\n\n [buildout]\n parts =\n ...\n nginx\n \n ...\n \n [nginx]\n recipe = zc.recipe.cmmi\n url = http://html-xslt.googlecode.com/files/nginx-0.7.65-html-xslt-2.tar.gz\n extra_options =\n --conf-path=${buildout:directory}/etc/nginx.conf\n --sbin-path=${buildout:directory}/bin\n --error-log-path=${buildout:directory}/var/log/nginx-error.log\n --http-log-path=${buildout:directory}/var/log/nginx-access.log\n --pid-path=${buildout:directory}/var/nginx.pid\n --lock-path=${buildout:directory}/var/nginx.lock\n --with-http_stub_status_module\n --with-http_xslt_module\n\nIf libxml2 or libxslt are installed in a non-standard location you may need to\nsupply the ``--with-libxml2=<path>`` and ``--with-libxslt=<path>`` options.\nThis requires that you set an appropriate ``LD_LIBRARY_PATH`` (Linux / BSD) or\n``DYLD_LIBRARY_PATH`` (Mac OS X) environment variable when running nginx.\n\nFor theming a static site, enable the XSLT transform in the nginx\nconfiguration as follows::\n\n location / {\n xslt_stylesheet /path/to/compiled-theme.xsl;\n xslt_html_parser on;\n xslt_types text/html;\n }\n\nnginx may also be configured as a transforming proxy server::\n\n location / {\n xslt_stylesheet /path/to/compiled-theme.xsl;\n xslt_html_parser on;\n xslt_types text/html;\n rewrite ^(.*)$ /VirtualHostBase/http/localhost/Plone/VirtualHostRoot$1 break;\n proxy_pass http://127.0.0.1:8080;\n proxy_set_header Host $host;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-XDV \"true\";\n proxy_set_header Accept-Encoding \"\";\n }\n\nRemoving the Accept-Encoding header is sometimes necessary to prevent the\nbackend server compressing the response (and preventing transformation). The\nresponse may be compressed in nginx by setting ``gzip on;`` - see the `gzip\nmodule documentation <http://wiki.nginx.org/NginxHttpGzipModule>`_ for\ndetails.\n\nIn this example an X-XDV header was set so the backend server may choose to\nserve different different CSS resources.\n\nIncluding external content\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAs an event based server, it is not practical to add ``document()`` support to\nthe nginx XSLT module for in-transform inclusion. Instead, external content is\nincluded through SSI in a sub-request. The SSI sub-request includes a query\nstring parameter to indicate which parts of the resultant document to include,\ncalled ``;filter_xpath`` - see above for a full example. The configuration\nbelow uses this parameter to apply a filter::\n\n worker_processes 1;\n events {\n worker_connections 1024;\n }\n http {\n include mime.types;\n gzip on;\n server {\n listen 80;\n server_name localhost;\n root html;\n\n # Decide if we need to filter\n if ($args ~ \"^(.*);filter_xpath=(.*)$\") {\n set $newargs $1;\n set $filter_xpath $2;\n # rewrite args to avoid looping\n rewrite ^(.*)$ /_include$1?$newargs?;\n }\n\n location @include500 { return 500; }\n location @include404 { return 404; }\n\n location ^~ /_include {\n # Restrict _include (but not ?;filter_xpath=) to subrequests\n internal;\n error_page 404 = @include404;\n # Cache page fragments in Varnish for 1h when using ESI mode\n expires 1h;\n # Proxy\n rewrite ^/_include(.*)$ $1 break;\n proxy_pass http://127.0.0.1:80;\n # Protect against infinite loops\n proxy_set_header X-Loop 1$http_X_Loop; # unary count\n proxy_set_header Accept-Encoding \"\";\n error_page 500 = @include500;\n if ($http_X_Loop ~ \"11111\") {\n return 500;\n }\n # Filter by xpath\n xslt_stylesheet filter.xsl\n xpath=$filter_xpath\n ;\n xslt_html_parser on;\n xslt_types text/html;\n }\n\n location / {\n xslt_stylesheet theme.xsl;\n xslt_html_parser on;\n xslt_types text/html;\n ssi on; # Not required in ESI mode\n }\n }\n }\n\nIn this example the sub-request is set to loop back on itself, so the include\nis taken from a themed page. ``filter.xsl`` (in the lib/xdv directory) and\n``theme.xsl`` should both be placed in the same directory as ``nginx.conf``.\n\nAn example buildout is available in ``nginx.cfg`` in this package.\n\nVarnish\n-------\n\nTo enable ESI in Varnish simply add the following to your VCL file::\n\n sub vcl_fetch {\n if (obj.http.Content-Type ~ \"text/html\") {\n esi;\n }\n }\n\nAn example buildout is available in ``varnish.cfg``.\n\nApache\n------\n\nXDV currently requires a version of mod_transform with html parsing support\nand a disabled mod_depends. The latest patched versions may be downloaded from\nthe `html-xslt project page <http://code.google.com/p/html-xslt/>`_.\n\nAs well as the libxml2 and libxslt development packages, you will require\nlibapreq2 and the Apache development pacakges::\n\n $ sudo apt-get install libxslt1-dev libapache2-mod-apreq2 libapreq2-dev \\\n > apache2-threaded-dev\n\nInstall mod_depends then mod_transform using the standard procedure::\n\n $ ./configure\n $ make\n $ sudo make install\n\nAn example virtual host configuration is shown below::\n\n NameVirtualHost *\n LoadModule depends_module /usr/lib/apache2/modules/mod_depends.so\n LoadModule transform_module /usr/lib/apache2/modules/mod_transform.so\n <VirtualHost *>\n\n FilterDeclare THEME\n FilterProvider THEME XSLT resp=Content-Type $text/html\n\n TransformOptions +ApacheFS +HTML\n TransformSet /theme.xsl\n TransformCache /theme.xsl /etc/apache2/theme.xsl\n\n <LocationMatch \"/\">\n FilterChain THEME\n </LocationMatch>\n \n </VirtualHost>\n\nThe +ApacheFS directive enables XSLT ``document()`` inclusion.\n\nUnfortunately it is not possible to theme error responses (such as a 404 Not\nFound page) with Apache as these do not pass through the filter chain.\n\n.. _Deliverance: http://deliveranceproject.org/\n\n\nChangelog\n=========\n\n0.3 - 2010-05-29\n----------------\n\n* Added access control defaults, xdv.utils.AC_READ_NET, xdv.utils.AC_READ_FILE\n\n0.3rc2 - 2010-05-25\n-------------------\n\nNote: the current lxml Windows binaries are unable to load files over the\nnetwork.\n\n* Fixed bug resolving the rules files while use a network theme.\n [elro]\n\n0.3rc1 - 2010-05-23\n-------------------\n\n* Nested <rules> are now allowed, so you can simply::\n\n ``<xi:include href=\"standard-rules.xml\" />``\n\n [elro]\n\n* XInclude processing is now enabled by default\n [elro]\n\n* XSL directives inlined in the rules file are now supported (e.g.\n <xsl:strip-space elements=\"*\" />). With the inline XSL support, there should\n now be no need for extra.xsl.\n [elro]\n\n* libxml2 quotes CR characters on output, causing Firefox to insert extra\n blank lines in ``<pre>`` blocks. As HTTP specified CRLF line endings for\n form this was a problem for us. This is now caught by the compiled XSL.\n [elro]\n\n* Support for including complete fragment documents with SSI/ESI.\n [elro]\n\n* A bug on namespace upgrade is fixed, but you should update your namespace to\n http://namespaces.plone.org/xdv anyway.\n [elro]\n\n* First release candidate.\n [elro]", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": null, "license": "New BSD", "maintainer": null, "maintainer_email": null, "name": "xdv", "package_url": "https://pypi.org/project/xdv/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/xdv/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/xdv/0.3/", "requires_dist": null, "requires_python": null, "summary": "XDV implements a subset of Deliverance using a pure XSLT engine. With XDV, you\n\"compile\" your theme and ruleset in one step, then use a superfast/simple\ntransform on each request thereafter. Alternatively, compile your theme during\ndevelopment, check it into Subversion, and not touch XDV during deployment.", "version": "0.3" }, "last_serial": 801813, "releases": { "0.1": [], "0.3": [ { "comment_text": "", "digests": { "md5": "0d1381244c35ef076ca758ad947fd8b6", "sha256": "b11b6333a623e530888cb96f4dcbbfabffca5e3848141c89af6e9145417493db" }, "downloads": -1, "filename": "xdv-0.3.tar.gz", "has_sig": false, "md5_digest": "0d1381244c35ef076ca758ad947fd8b6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 169292, "upload_time": "2010-05-29T10:53:21", "url": "https://files.pythonhosted.org/packages/bf/a7/62aec960f0cb27a6572d7299eecba5a84dc01687666f241881b92bca9202/xdv-0.3.tar.gz" } ], "0.3a1": [ { "comment_text": "", "digests": { "md5": "cf5750459660c1784b7c81002f6dc647", "sha256": "1e591a158d3e0478b1cce8fcae0ae2b1e506d5af6ef58bc2906b446674afc117" }, "downloads": -1, "filename": "xdv-0.3a1.tar.gz", "has_sig": false, "md5_digest": "cf5750459660c1784b7c81002f6dc647", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 93916, "upload_time": "2010-01-23T00:41:12", "url": "https://files.pythonhosted.org/packages/92/a6/dd64b95b627bacb4d9d8cc2aa197875a8db12f014faa955881b5f3a036b0/xdv-0.3a1.tar.gz" } ], "0.3a2": [ { "comment_text": "", "digests": { "md5": "dcb30a9318102444205d77860820d22a", "sha256": "340d8dc741933d5d955339d9fc45c0ea9622e3336b301e50b83999e5cce235f5" }, "downloads": -1, "filename": "xdv-0.3a2.tar.gz", "has_sig": false, "md5_digest": "dcb30a9318102444205d77860820d22a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 157569, "upload_time": "2010-03-24T03:15:49", "url": "https://files.pythonhosted.org/packages/f4/c5/706e47f9f64868ab197e74146cd4350696147e83cdcd76fa36d1fe337c6e/xdv-0.3a2.tar.gz" } ], "0.3a3": [ { "comment_text": "", "digests": { "md5": "3313278eb5f464763fb9409c2d6273e6", "sha256": "b604e16a0b551111b59ccf15f4ba90da3ce255450bd1110cfa02ad3ab125acf6" }, "downloads": -1, "filename": "xdv-0.3a3.zip", "has_sig": false, "md5_digest": "3313278eb5f464763fb9409c2d6273e6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 220354, "upload_time": "2010-04-21T18:31:31", "url": "https://files.pythonhosted.org/packages/c1/a1/920b3a54fa4884b1deca9a2c72cdfdc3215e2f98e20a340acb4bad9b83c4/xdv-0.3a3.zip" } ], "0.3rc1": [ { "comment_text": "", "digests": { "md5": "ac86f1827aa4eed5cf6cdc5ac3ce0496", "sha256": "346645336a5e7c1b5d75391777f6f8c82fb3bff37e5e3eddef13280d8bfc5e75" }, "downloads": -1, "filename": "xdv-0.3rc1.tar.gz", "has_sig": false, "md5_digest": "ac86f1827aa4eed5cf6cdc5ac3ce0496", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 167540, "upload_time": "2010-05-23T23:16:57", "url": "https://files.pythonhosted.org/packages/c9/83/a56b8d82ec0b4fdb70cc9648ffe6e5878c6318818445951e28d844ee4bc2/xdv-0.3rc1.tar.gz" } ], "0.3rc2": [ { "comment_text": "", "digests": { "md5": "8585e92d976c320c9cd55a637c4f52a2", "sha256": "1cc456778e257b82a0e81201aab2850b8152e5cef3b2b50f1ba56014518109a1" }, "downloads": -1, "filename": "xdv-0.3rc2.tar.gz", "has_sig": false, "md5_digest": "8585e92d976c320c9cd55a637c4f52a2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 168514, "upload_time": "2010-05-25T14:08:29", "url": "https://files.pythonhosted.org/packages/f1/dc/6dd8838c74524aa739ad2779cd5c15fb329c801ccc506d3da1d865967013/xdv-0.3rc2.tar.gz" } ], "0.4b1": [ { "comment_text": "", "digests": { "md5": "4ae1ada47c563001c7d7b9bdc0197c2b", "sha256": "29c082a3eeac2b223471b79da0a2546135a2050390d7af90b4de4ef1861cdd17" }, "downloads": -1, "filename": "xdv-0.4b1.tar.gz", "has_sig": false, "md5_digest": "4ae1ada47c563001c7d7b9bdc0197c2b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 176718, "upload_time": "2010-08-06T17:58:38", "url": "https://files.pythonhosted.org/packages/ea/be/c09b58c60297a0980008fa63b9a9d31b0e590d022660dad2f6157bd12a04/xdv-0.4b1.tar.gz" } ], "0.4b2": [ { "comment_text": "", "digests": { "md5": "7f0c94cb6b15272fad010f494d5198fb", "sha256": "02a496a61fa516ec0f299daf5b661bee9930965d017215332cc436dca9266dff" }, "downloads": -1, "filename": "xdv-0.4b2.tar.gz", "has_sig": false, "md5_digest": "7f0c94cb6b15272fad010f494d5198fb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 174904, "upload_time": "2010-08-16T20:54:42", "url": "https://files.pythonhosted.org/packages/15/48/a0b71c523d340961c075d89acdadb1c3c1c39e3e0023b32cada152b20376/xdv-0.4b2.tar.gz" } ], "0.4b3": [ { "comment_text": "", "digests": { "md5": "d05c27f0a6dffb63dfa09b392c12cfba", "sha256": "d17880de5b80800ea41b3203994ad6bbdbb6adae830a6a0e738281862e3f4fbb" }, "downloads": -1, "filename": "xdv-0.4b3.tar.gz", "has_sig": false, "md5_digest": "d05c27f0a6dffb63dfa09b392c12cfba", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 184187, "upload_time": "2010-09-09T20:47:26", "url": "https://files.pythonhosted.org/packages/0f/61/09424c766d2682809b8471c2167d0515c044f004ff92e8ea62205b1fa10c/xdv-0.4b3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0d1381244c35ef076ca758ad947fd8b6", "sha256": "b11b6333a623e530888cb96f4dcbbfabffca5e3848141c89af6e9145417493db" }, "downloads": -1, "filename": "xdv-0.3.tar.gz", "has_sig": false, "md5_digest": "0d1381244c35ef076ca758ad947fd8b6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 169292, "upload_time": "2010-05-29T10:53:21", "url": "https://files.pythonhosted.org/packages/bf/a7/62aec960f0cb27a6572d7299eecba5a84dc01687666f241881b92bca9202/xdv-0.3.tar.gz" } ] }