forked from lix-project/lix
primops: Move toXML to primops/toXML.cc
Change-Id: I8da29345903015e38b9832f0d9b4011dc5bbb17b
This commit is contained in:
parent
a93af3f92f
commit
c96f5bcdd2
|
@ -103,6 +103,7 @@ libexpr_sources = files(
|
||||||
'primops/path.cc',
|
'primops/path.cc',
|
||||||
'primops/string.cc',
|
'primops/string.cc',
|
||||||
'primops/system.cc',
|
'primops/system.cc',
|
||||||
|
'primops/toXML.cc',
|
||||||
'primops/types.cc',
|
'primops/types.cc',
|
||||||
'value/context.cc',
|
'value/context.cc',
|
||||||
)
|
)
|
||||||
|
|
|
@ -186,110 +186,6 @@ static void derivationStrictInternal(EvalState & state, const std::string & name
|
||||||
/* Convert the argument (which can be any Nix expression) to an XML
|
/* Convert the argument (which can be any Nix expression) to an XML
|
||||||
representation returned in a string. Not all Nix expressions can
|
representation returned in a string. Not all Nix expressions can
|
||||||
be sensibly or completely represented (e.g., functions). */
|
be sensibly or completely represented (e.g., functions). */
|
||||||
static void prim_toXML(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
|
||||||
{
|
|
||||||
std::ostringstream out;
|
|
||||||
NixStringContext context;
|
|
||||||
printValueAsXML(state, true, false, *args[0], out, context, pos);
|
|
||||||
v.mkString(out.str(), context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static RegisterPrimOp primop_toXML({
|
|
||||||
.name = "__toXML",
|
|
||||||
.args = {"e"},
|
|
||||||
.doc = R"(
|
|
||||||
Return a string containing an XML representation of *e*. The main
|
|
||||||
application for `toXML` is to communicate information with the
|
|
||||||
builder in a more structured format than plain environment
|
|
||||||
variables.
|
|
||||||
|
|
||||||
Here is an example where this is the case:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ stdenv, fetchurl, libxslt, jira, uberwiki }:
|
|
||||||
|
|
||||||
stdenv.mkDerivation (rec {
|
|
||||||
name = "web-server";
|
|
||||||
|
|
||||||
buildInputs = [ libxslt ];
|
|
||||||
|
|
||||||
builder = builtins.toFile "builder.sh" "
|
|
||||||
source $stdenv/setup
|
|
||||||
mkdir $out
|
|
||||||
echo "$servlets" | xsltproc ${stylesheet} - > $out/server-conf.xml ①
|
|
||||||
";
|
|
||||||
|
|
||||||
stylesheet = builtins.toFile "stylesheet.xsl" ②
|
|
||||||
"<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
|
|
||||||
<xsl:template match='/'>
|
|
||||||
<Configure>
|
|
||||||
<xsl:for-each select='/expr/list/attrs'>
|
|
||||||
<Call name='addWebApplication'>
|
|
||||||
<Arg><xsl:value-of select=\"attr[@name = 'path']/string/@value\" /></Arg>
|
|
||||||
<Arg><xsl:value-of select=\"attr[@name = 'war']/path/@value\" /></Arg>
|
|
||||||
</Call>
|
|
||||||
</xsl:for-each>
|
|
||||||
</Configure>
|
|
||||||
</xsl:template>
|
|
||||||
</xsl:stylesheet>
|
|
||||||
";
|
|
||||||
|
|
||||||
servlets = builtins.toXML [ ③
|
|
||||||
{ path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; }
|
|
||||||
{ path = "/wiki"; war = uberwiki + "/uberwiki.war"; }
|
|
||||||
];
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
The builder is supposed to generate the configuration file for a
|
|
||||||
[Jetty servlet container](http://jetty.mortbay.org/). A servlet
|
|
||||||
container contains a number of servlets (`*.war` files) each
|
|
||||||
exported under a specific URI prefix. So the servlet configuration
|
|
||||||
is a list of sets containing the `path` and `war` of the servlet
|
|
||||||
(①). This kind of information is difficult to communicate with the
|
|
||||||
normal method of passing information through an environment
|
|
||||||
variable, which just concatenates everything together into a
|
|
||||||
string (which might just work in this case, but wouldn’t work if
|
|
||||||
fields are optional or contain lists themselves). Instead the Nix
|
|
||||||
expression is converted to an XML representation with `toXML`,
|
|
||||||
which is unambiguous and can easily be processed with the
|
|
||||||
appropriate tools. For instance, in the example an XSLT stylesheet
|
|
||||||
(at point ②) is applied to it (at point ①) to generate the XML
|
|
||||||
configuration file for the Jetty server. The XML representation
|
|
||||||
produced at point ③ by `toXML` is as follows:
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<?xml version='1.0' encoding='utf-8'?>
|
|
||||||
<expr>
|
|
||||||
<list>
|
|
||||||
<attrs>
|
|
||||||
<attr name="path">
|
|
||||||
<string value="/bugtracker" />
|
|
||||||
</attr>
|
|
||||||
<attr name="war">
|
|
||||||
<path value="/nix/store/d1jh9pasa7k2...-jira/lib/atlassian-jira.war" />
|
|
||||||
</attr>
|
|
||||||
</attrs>
|
|
||||||
<attrs>
|
|
||||||
<attr name="path">
|
|
||||||
<string value="/wiki" />
|
|
||||||
</attr>
|
|
||||||
<attr name="war">
|
|
||||||
<path value="/nix/store/y6423b1yi4sx...-uberwiki/uberwiki.war" />
|
|
||||||
</attr>
|
|
||||||
</attrs>
|
|
||||||
</list>
|
|
||||||
</expr>
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that we used the `toFile` built-in to write the builder and
|
|
||||||
the stylesheet “inline” in the Nix expression. The path of the
|
|
||||||
stylesheet is spliced into the builder using the syntax `xsltproc
|
|
||||||
${stylesheet}`.
|
|
||||||
)",
|
|
||||||
.fun = prim_toXML,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/* Store a string in the Nix store as a source file that can be used
|
/* Store a string in the Nix store as a source file that can be used
|
||||||
|
|
115
src/libexpr/primops/toXML.cc
Normal file
115
src/libexpr/primops/toXML.cc
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
#include "primops.hh"
|
||||||
|
#include "value-to-xml.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* builtins.toXML
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void prim_toXML(EvalState & state, const PosIdx pos, Value ** args, Value & v)
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
NixStringContext context;
|
||||||
|
printValueAsXML(state, true, false, *args[0], out, context, pos);
|
||||||
|
v.mkString(out.str(), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterPrimOp primop_toXML({
|
||||||
|
.name = "__toXML",
|
||||||
|
.args = {"e"},
|
||||||
|
.doc = R"(
|
||||||
|
Return a string containing an XML representation of *e*. The main
|
||||||
|
application for `toXML` is to communicate information with the
|
||||||
|
builder in a more structured format than plain environment
|
||||||
|
variables.
|
||||||
|
|
||||||
|
Here is an example where this is the case:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ stdenv, fetchurl, libxslt, jira, uberwiki }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation (rec {
|
||||||
|
name = "web-server";
|
||||||
|
|
||||||
|
buildInputs = [ libxslt ];
|
||||||
|
|
||||||
|
builder = builtins.toFile "builder.sh" "
|
||||||
|
source $stdenv/setup
|
||||||
|
mkdir $out
|
||||||
|
echo "$servlets" | xsltproc ${stylesheet} - > $out/server-conf.xml ①
|
||||||
|
";
|
||||||
|
|
||||||
|
stylesheet = builtins.toFile "stylesheet.xsl" ②
|
||||||
|
"<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
|
||||||
|
<xsl:template match='/'>
|
||||||
|
<Configure>
|
||||||
|
<xsl:for-each select='/expr/list/attrs'>
|
||||||
|
<Call name='addWebApplication'>
|
||||||
|
<Arg><xsl:value-of select=\"attr[@name = 'path']/string/@value\" /></Arg>
|
||||||
|
<Arg><xsl:value-of select=\"attr[@name = 'war']/path/@value\" /></Arg>
|
||||||
|
</Call>
|
||||||
|
</xsl:for-each>
|
||||||
|
</Configure>
|
||||||
|
</xsl:template>
|
||||||
|
</xsl:stylesheet>
|
||||||
|
";
|
||||||
|
|
||||||
|
servlets = builtins.toXML [ ③
|
||||||
|
{ path = "/bugtracker"; war = jira + "/lib/atlassian-jira.war"; }
|
||||||
|
{ path = "/wiki"; war = uberwiki + "/uberwiki.war"; }
|
||||||
|
];
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The builder is supposed to generate the configuration file for a
|
||||||
|
[Jetty servlet container](http://jetty.mortbay.org/). A servlet
|
||||||
|
container contains a number of servlets (`*.war` files) each
|
||||||
|
exported under a specific URI prefix. So the servlet configuration
|
||||||
|
is a list of sets containing the `path` and `war` of the servlet
|
||||||
|
(①). This kind of information is difficult to communicate with the
|
||||||
|
normal method of passing information through an environment
|
||||||
|
variable, which just concatenates everything together into a
|
||||||
|
string (which might just work in this case, but wouldn’t work if
|
||||||
|
fields are optional or contain lists themselves). Instead the Nix
|
||||||
|
expression is converted to an XML representation with `toXML`,
|
||||||
|
which is unambiguous and can easily be processed with the
|
||||||
|
appropriate tools. For instance, in the example an XSLT stylesheet
|
||||||
|
(at point ②) is applied to it (at point ①) to generate the XML
|
||||||
|
configuration file for the Jetty server. The XML representation
|
||||||
|
produced at point ③ by `toXML` is as follows:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<expr>
|
||||||
|
<list>
|
||||||
|
<attrs>
|
||||||
|
<attr name="path">
|
||||||
|
<string value="/bugtracker" />
|
||||||
|
</attr>
|
||||||
|
<attr name="war">
|
||||||
|
<path value="/nix/store/d1jh9pasa7k2...-jira/lib/atlassian-jira.war" />
|
||||||
|
</attr>
|
||||||
|
</attrs>
|
||||||
|
<attrs>
|
||||||
|
<attr name="path">
|
||||||
|
<string value="/wiki" />
|
||||||
|
</attr>
|
||||||
|
<attr name="war">
|
||||||
|
<path value="/nix/store/y6423b1yi4sx...-uberwiki/uberwiki.war" />
|
||||||
|
</attr>
|
||||||
|
</attrs>
|
||||||
|
</list>
|
||||||
|
</expr>
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that we used the `toFile` built-in to write the builder and
|
||||||
|
the stylesheet “inline” in the Nix expression. The path of the
|
||||||
|
stylesheet is spliced into the builder using the syntax `xsltproc
|
||||||
|
${stylesheet}`.
|
||||||
|
)",
|
||||||
|
.fun = prim_toXML,
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue