523
521
return ::compose(m);
524
object find_xml(void|object xml)
530
if ( objectp(oEnvironment) ) {
531
xml = oEnvironment->get_object_byname(get_identifier()+".xml");
532
sscanf(get_identifier(), "%s.%*s", name);
534
if ( !objectp(xml) ) {
535
xml = oEnvironment->get_object_byname(name+".xgl");
539
xml = do_query_attribute(DOC_XSL_XML);
541
// fall back to public Stylesheet, if available
542
if ( !objectp(xml) || xml->status() < 0 || xml->status() == PSTAT_DELETED ) {
543
xml = OBJ("/stylesheets/public.xsl.xml");
548
array load_imports(object n)
552
nodes = n->get_nodes("language");
556
foreach(nodes, object node) {
557
array(object) imports = ({ });
559
if ( stringp(node->attributes->auto) ) {
560
object languageCont = OBJ("/languages");
561
if ( objectp(languageCont) ) {
562
array(object) languageNodes = ({ });
563
foreach( languageCont->get_inventory_by_class(CLASS_DOCXML), object langXML)
565
NodeXML langnode = xmlCache.parse(langXML);
566
imports += langnode->get_nodes("import");
567
languageNodes += ({ langnode });
569
node->replace_node( languageNodes );
573
imports = node->get_nodes("import");
575
foreach(imports, object imp) {
577
object import_obj = parse_import(imp->attributes->file);
578
if ( !objectp(import_obj) ) continue;
579
imp->replace_node(import_obj,
580
imp->attributes->xpath);
583
if ( !stringp(imp->attributes->file) )
584
FATAL("Importing language: "+
585
"Missing file attribute on %s tag !",
588
FATAL("Failed to import file: %s, %O\n%O",
589
imp->attributes->file, e[0], e[1]);
597
static int in_backtrace(object obj)
599
if ( !objectp(obj) || !functionp(obj->get_object) ||
600
!objectp(obj->get_object()) )
603
foreach( backtrace(), mixed preceed ) {
604
if ( function_object(preceed[2]) == obj->get_object() )
611
* Load the related xgl (or xsl.xml) document
531
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
534
void load_xml_structure()
614
void load_xml_structure(void|object xml)
616
if ( in_backtrace(get_module("tar")) ) {
617
call(load_xml_structure, 1);
621
if ( do_query_attribute(OBJ_VERSIONOF) || this()->status() < 0 || this()->status() == PSTAT_DELETED )
622
return; // do not load xml for old versions
536
624
// factories must be loaded
537
625
if ( !objectp(get_factory(CLASS_OBJECT)) ) {
538
626
call(load_xml_structure, 1);
541
object xmlLock = xmlMutex->lock();
630
object xmlLock = xmlMutex->trylock();
631
if ( !objectp(xmlLock) )
632
steam_error("Failed to obtain xml-lock in %O", get_identifier());
542
634
mixed xmlErr = catch {
543
if ( objectp(oEnvironment) ) {
544
object xml = oEnvironment->get_object_byname(get_identifier()+".xml");
545
if ( !objectp(xml) ) {
547
sscanf(get_identifier(), "%s.%*s", name);
548
xml = oEnvironment->get_object_byname(name+".xgl");
550
if ( !objectp(xml) ) {
552
xml = OBJ("/stylesheets/public.xsl.xml");
554
if ( objectp(xml) ) {
556
MESSAGE("Loading XML of " + xml->get_identifier());
557
if ( !objectp(mUpdates[xml]) )
558
mUpdates[xml] = UpdateListener(xml, this());
561
NodeXML n = parse_data(xml->get_content());
562
array nodes = n->get_nodes("language");
564
if ( arrayp(nodes) ) {
565
foreach(nodes, object node) {
566
array(object) imports = node->get_nodes("import");
567
foreach(imports, object imp) {
570
imp->replace_node(read_import(imp->attributes->file),
571
imp->attributes->xpath);
574
FATAL("Failed to import file: %s, %O",
575
imp->attributes->file, e);
579
mLang = read_languages(n->get_nodes("language"));
582
MESSAGE("No imports found, no languages for %s!",
588
throw( ({ "Root node '<structure>' not found in "+
589
"XML description file !", backtrace() }) );
590
if ( n->name == "structure" ) {
592
if ( (stringp(n->attributes->generate) &&
593
n->attributes->generate == "pike") ||
594
stringp(n->get_pi()["steam"]) )
595
hook_xml(xml->get_content());
602
FATAL("Error while generating xml map ["
603
+_FILEPATH->object_to_filename(xml)+"]:\n"+err[0]+
604
sprintf("%O",err[1]));
605
if ( CALLER != this_object() ) {
615
if ( CALLER != this_object() ) {
617
THROW("No description file ("+get_identifier()
618
+".xml) found for Stylesheet !", E_ERROR);
636
if ( objectp(xml) ) {
637
if ( !objectp(mUpdates[xml]) )
638
mUpdates[xml] = UpdateListener(xml, this());
640
NodeXML n = parse_data(xml->get_content());
641
array nodes = load_imports(n);
642
mLang = read_languages(nodes);
644
object xmlscript = do_query_attribute(DOC_XSL_PIKE);
647
throw( ({ "Root node '<structure>' not found in "+
648
"XML description file !", backtrace() }) );
650
if ( n->name == "structure" ) {
651
if ( (stringp(n->attributes->generate) &&
652
n->attributes->generate == "pike") ||
653
stringp(n->get_pi()["steam"]) )
658
if ( objectp(xmlscript) )
660
do_set_attribute(DOC_XSL_PIKE);
666
if ( CALLER != this_object() ) {
668
FATAL("No description file ("+get_identifier()+".xml) found for Stylesheet !");
624
FATAL("Failed to load xml structure for " + get_identifier() + "\n"+
625
sprintf("%O\n", xmlErr));
676
FATAL("Failed to load xml structure for %s\n%O",
677
_FILEPATH->object_to_filename(this_object()),
680
if ( CALLER != this_object() ) {
629
685
destruct(xmlLock);
632
688
static string read_import(string fname)
634
690
object f = _FILEPATH->path_to_object(fname);
637
694
if ( !objectp(mUpdates[f]) )
638
695
mUpdates[f] = UpdateListener(f, this());
639
696
return f->get_content();
642
static object hook_xml(string xml)
699
static object parse_import(string fname)
701
object f = _FILEPATH->path_to_object(fname);
705
if ( !objectp(mUpdates[f]) )
706
mUpdates[f] = UpdateListener(f, this());
707
return xmlCache.parse(f);
710
int check_xgl_consistency(object xmlscript, object xmlObj)
712
if ( objectp(xmlscript) ) {
713
object script_xml = xmlscript->query_attribute(DOCLPC_XGL);
714
object xgl = do_query_attribute(DOC_XSL_XML);
715
if ( objectp(script_xml) && xgl != script_xml )
717
FATAL("DocXSL: mismatched Pike-Script and XGL File !\n%s(%O): %s(%O)",
718
(objectp(script_xml)?script_xml->get_identifier(): "null"),
720
(objectp(xgl)?xgl->get_identifier():"null"),
722
do_set_attribute(DOC_XSL_XML);
723
xmlObj->set_attribute(DOC_LAST_MODIFIED, time());
731
static void hook_xml(object xmlObj, void|object rootNode)
644
733
object xmlscript = do_query_attribute(DOC_XSL_PIKE);
646
string pikecode = XMLCodegen.codegen(xml, read_import);
735
check_xgl_consistency(xmlscript, xmlObj);
736
if ( xmlObj == OBJ("/stylesheets/public.xsl.xml") ) {
737
object oxgl = do_query_attribute(DOC_XSL_XML);
742
if (objectp(xmlscript))
743
tss = xmlscript->query_attribute(DOCLPC_INSTANCETIME);
744
int tsc = xmlObj->query_attribute(DOC_LAST_MODIFIED);
746
DEBUG_DOCXSL("Timestamp test when hooking XML: (tss=%d, tsc=%d)", tss, tsc);
747
// also see if XGL file has not changed !
748
if ( tss > tsc && do_query_attribute(DOC_XSL_XML) == xmlObj )
751
string pikecode = XMLCodegen.codegen(xmlObj, read_import);
752
set_attribute(DOC_XSL_XML, xmlObj);
754
DEBUG_DOCXSL("Updating Pike XML Generation ...");
755
string scriptname = get_object_id() + ".pike";
647
756
if ( !objectp(xmlscript) )
648
xmlscript = get_factory(CLASS_DOCUMENT)->execute(([ "name": "xml.pike",]));
757
xmlscript = get_factory(CLASS_DOCUMENT)->execute(([ "name": scriptname,]));
651
760
do_set_attribute(DOC_XSL_PIKE, xmlscript);
761
xmlscript->set_attribute(DOCLPC_XGL, xmlObj);
763
if ( !check_xgl_consistency(xmlscript, xmlObj) )
764
steam_error("DocXSL: consistency check failed .... !");
652
766
err = catch(xmlscript->set_content(pikecode));
767
if ( arrayp(xmlscript->get_errors()) && sizeof(xmlscript->get_errors()) > 0 ) {
768
FATAL("Errors in xml Script: %O", xmlscript->get_errors());
770
catch(xmlscript->sanction_object(GROUP("everyone"),SANCTION_READ|SANCTION_EXECUTE));
654
772
FATAL("Failed to hook xml content: %s", err[0]);
655
773
xmlscript->provide_instance(); // should create an instance when loaded
1003
1090
bool check_swap() { return false; } // do not swap out stylesheets
1004
1091
int get_object_class() { return ::get_object_class() | CLASS_DOCXSL; }
1092
string get_class() { return "DocXSL"; }
1097
// check xsl.xml here...
1098
MESSAGE("* Testing DocXSL functionality and libxslt ...");
1099
MESSAGE("Creating test container...");
1100
object testcont = OBJ("/home/steam/__xsltestcont");
1101
if ( !objectp(testcont) ) {
1102
testcont=get_factory(CLASS_CONTAINER)->execute( (["name":"__xsltestcont"]) );
1103
testcont->move(OBJ("/home/steam"));
1105
foreach(testcont->get_inventory(), object inv) {
1111
MESSAGE("Creating language file...");
1112
object languages = get_factory(CLASS_DOCUMENT)->execute( (["name":"terms.xml",]) );
1113
MESSAGE("Language file is %O", languages);
1114
languages->set_content("<?xml version='1.0' encoding='utf-8'?>\n<language><term name='TERM1'>term_1</term></language>\n");
1115
languages->move(testcont);
1117
string pathname = _FILEPATH->object_to_filename(languages);
1119
MESSAGE("Creating XGL File...");
1120
object xgl = get_factory(CLASS_DOCUMENT)->execute( (["name": "test.xgl", ]) );
1121
xgl->set_content("<?xml version='1.0' encoding='utf-8'?>\n<structure generate='pike'>\n<class type='Object'>\n<tag name='test'><call><function name='get_identifier' /></call><show><function name='show' /></show></tag></class><language name='english'><import file='"+pathname+"' xpath='term' /></language>\n</structure>\n");
1123
xgl->move(testcont);
1124
MESSAGE("Testing xsl...");
1125
set_content("<?xml version='1.0' encoding='utf-8'?>\n<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>\n<xsl:output method='html' encoding='utf-8' />\n<xsl:template match='Object/test'>{TERM1}: testing</xsl:template>\n</xsl:stylesheet>");
1126
load_xml_structure(xgl);
1128
object pikescript = do_query_attribute(DOC_XSL_PIKE);
1129
if ( !objectp(pikescript) )
1130
steam_error("Generation of Pike-Script failed !");
1132
MESSAGE("Looking for UpdateListener ...");
1133
if ( !objectp(mUpdates[xgl]) )
1134
steam_error("No Update Listener for XGL ...");
1135
if ( !objectp(mUpdates[languages]) ) {
1136
MESSAGE("Dumping Update Listeners:\n%O", indices(mUpdates));
1137
steam_error("No Update Listener for Language Term File (%O) ...", languages);
1139
call(test_more, 1, pikescript, xgl, languages, testcont, "", 0);
1142
void test_more(object pikescript, object xgl, object languages, object testcont, string xml, int test)
1144
if ( pikescript->status() != PSTAT_DISK ) {
1146
call(test_more, 5, pikescript, xgl, languages, testcont, xml, test);
1151
MESSAGE("Testing xml generation !");
1152
mapping params = ([ "this_user": USER("root")->get_object_id(), ]);
1153
xml = get_module("Converter:XML")->get_xml(this(), this(), params);
1154
// xgl file controls xml generatoin - should be simple xml
1155
MESSAGE("XML Generated: \n%s---", xml);
1156
if ( search(xml, "XGL File: "+_FILEPATH->object_to_filename(xgl)) == -1 )
1157
steam_error("XGL Test: Used wrong xgl file for XML Generation !");
1158
string result = get_module("libxslt")->run(xml, this(), ([ ]));
1159
MESSAGE("OUTPUT = %s", result);
1160
call(test_more, 2, pikescript, xgl, languages, testcont, xml, 1);
1163
MESSAGE("Testing update of depend...");
1164
languages->set_content("<?xml version='1.0' encoding='utf-8'?>\n<language><term name='TERM1'>modified</term></language>\n");
1165
result = get_module("libxslt")->run(xml, this(), ([ ]));
1166
if ( search(result, "modified") == -1 )
1167
steam_error("Language File Update did not update Term Definition in %O !"+
1168
"\nDump: %s", languages, result);
1169
languages->delete();
1173
MESSAGE("* DocXSL.test() all tests finished successfully !");