📄 xslt.cpp
字号:
/*____________________________________________________________________________*\
*
Copyright (c) 1997-2003 John Roy, Holger Zimmermann. All rights reserved.
These sources, libraries and applications are
FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
as long as the following conditions are adhered to.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHORS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*____________________________________________________________________________*|
*
* $Source: /cvsroot/pi3web/Pi3Web_200/Source/XSLT/XSLT.cpp,v $
* $Date: 2003/05/13 18:42:22 $
*
Description:
Execute an XSLT transformation on a XML (HTML or Docbook SGML) document
and send back the resulting document to the client.
\*____________________________________________________________________________*/
//$SourceTop:$
#include <iostream.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include "HandBase.h"
#include "HTTPCore.h"
#include "HTTPUtil.h"
#include "PIStrStr.h"
#include "DeQuote.h"
#include "PiAPI.h"
#include "StrToken.h"
#include <libxslt/libxslt.h>
#include <libexslt/exslt.h>
#include <libxml/xmlmemory.h>
#include <libxml/debugXML.h>
#include <libxml/HTMLtree.h>
#include <libxml/xmlIO.h>
#include <libxml/DOCBparser.h>
#include <libxml/HTMLparser.h>
#include <libxml/xinclude.h>
#include <libxml/catalog.h>
#include <libxml/parserInternals.h>
#include <libxml/uri.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <libxslt/imports.h>
/*
** #define D { cerr << __FILE__ << ": " << __LINE__ << endl; }
*/
#define D
/*____________________________________________________________________________*\
*
Description:
\*____________________________________________________________________________*/
#define MAX_PARAMETERS 64
#define KEY_CONF_DEFAULTSTYLESHEET "DefaultStylesheet"
#define KEY_CONF_CONTENTTYPE "DefaultContentType"
#define KEY_CONF_OPTIONS "Options"
#define KEY_CONF_MAXDEPTH "MaxDepth"
#define KEY_CONF_VARIABLE "Variable"
#define KEY_CONF_EXTRAHDRPREFIX "ExtraHeadersPrefix"
#define KEY_CONF_EXTRAHEADERSIGNORE "ExtraHeadersIgnore"
#define KEY_CONF_EXTRAHEADERS "ExtraHeaders"
#define VALUE_NO "No"
#define VALUE_YES "Yes"
/*____________________________________________________________________________*\
*
Flags and Options
\*____________________________________________________________________________*/
#define FLG_NONE 0x00000000
#define FLG_NODTD 0x00000001
#define FLG_VALIDATE 0x00000002
#define FLG_NONET 0x00000004
#define FLG_WARNNET 0x00000008
#define FLG_VERBOSE 0x00000010
#define FLG_XINCLUDE 0x00000020
#define FLG_CATALOGS 0x00000040
#define FLG_HTML 0x00000080
#define FLG_DOCBOOK 0x00000100
#define FLG_TIMING 0x00000200
#define FLG_PROFILE 0x00000400
#define FLG_DEBUG 0x00000800
/*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ *
Map these flags to names
*___ +++++++++++++++++++++++++++++++++++++++++++++++++ ___ */
struct {
const char *pName;
int iFlag;
} aFlagMap[] =
{
{ "SkipDtdLoading", FLG_NODTD },
{ "Validate", FLG_VALIDATE },
{ "NoNetEntities", FLG_NONET },
{ "WarnNetEntities",FLG_WARNNET },
{ "Verbose", FLG_VERBOSE },
{ "XInclude", FLG_XINCLUDE },
{ "SgmlCatalogs", FLG_CATALOGS },
{ "Html", FLG_HTML },
{ "Docbook", FLG_DOCBOOK },
{ "Timing", FLG_TIMING },
{ "Profile", FLG_PROFILE },
{ "Debug", FLG_DEBUG },
/* --- leave this last always --- */
{ 0, 0 }
};
/*____________________________________________________________________________*\
*
Description:
\*____________________________________________________________________________*/
#if 0
/*
** HTML documentation for this handler
*/
/*___+++HTMLDOC_BEGIN+++___*/
Name:
XSLT
Description:
The XSLT handler provides XSLT transformations based on libxml2
and libxslt. Further information about these libraries is available
at <a href="http://xmlsoft.org">http://xmlsoft.org</a>. The input
may be either an XML, HTML or Docbook SGML document. An XSL stylsesheet
is applied to the paresd XML document and the result is sent back to
the client. POST requests are also supported.
Options:
<TABLE BORDER=1>
<TH>Option
<TH>Default
<TH>Values
<TH>Short Description
<TH>Example(s)
<TR>
<TD>DefaultStylesheet
<TD>-
<TD><path name or URL>
<TD>A valid path name or URL to be used to load the XSLT stylesheet
<TD>DefaultStylesheet "./Default.xsl"
<TR>
<TD>DefaultContentType
<TD>-
<TD><a mime type string>
<TD>A valid mime type to overwrite XSLT engine selection
<TD>DefaultContentType "application/rtf"
<TR>
<TD>MaxDepth
<TD>500
<TD><a number>
<TD>The maximum depth of template stack
<TD>Example
<TR>
<TD>Variable
<TD>-
<TD><a Pi3Expression>
<TD>A variable definition
<TD>Variable "GATEWAY_INTERFACE=CGI/1.1"
<TR>
<TD>ExtraHeaders
<TD>Yes
<TD>Yes|No
<TD>Indicates if extra headers are considered
<TD>ExtraHeaders Yes
<TR>
<TD>ExtraHeadersPrefix
<TD>-
<TD><a string>
<TD>Used as prefix of each extra header
<TD>ExtraHeadersPrefix "HTTP_"
<TR>
<TD>ExtraHeadersIgnore
<TD>-
<TD><Space delimited strings>
<TD>List of unconsidered extra headers
<TD>ExtraHeadersIgnore "Content-Type Content-Length"
<TR>
<TD>Options
<TD>-
<TD>Options flags as described below
<TD>Options which effect behaviour
<TD>Options "NoNetEntities | Verbose"
</TABLE>
<STRONG>-</STRONG> in the <IT>default</IT> indicates no default<BR>
<STRONG>+</STRONG> in the <IT>default</IT> indicates the field is mandatory<BR>
<H4>Description of Options</H4>
<H5>DefaultStylesheet</H5>
This parameter is used to apply the given stylesheet instead the stylesheet
ignoring any stylesheet in the source file. A relative path is treated
from the current working directory, which is the directory from where the
server has been started. This is different to other external entity paths,
e.g. dtd or styleshet paths in an xml file.
<H5>DefaultContentType</H5>
This parameter is used to set the mime type used in the server response to
a given value. Otherwise the selection is done by the handler itself
supported by the XSLT engine.
<H5>MaxDepth</H5>
Adjust the maximum depth of the template stack before libxslt concludes it
is in an infinite loop. The default is 500.
<H5>Variable</H5>
Specifies a server variable expression to be set as a global stylesheet parameter.
Could be set multiple times in one configuration object up to 32.
<H5>ExtraHeaders</H5>
This configuration key defines, if extra headers are considered by
the processing of this handler as global stylesheet parameters.
<H5>ExtraHeadersPrefix</H5>
This configuration value will be the trailing string of each extra
request header.
<H5>ExtraHeadersIgnore</H5>
The headers in this list are not treated as extra headers.
<H5>Options</H5>
Specifies options which effect the behaviour of the XSLT transformations,
many available facilities are optional for performance reasons, the table
below lists the available option flags with their meanings.
<CENTER>
<TABLE BORDER=1>
<TH>Option
<TH>Meaning
<TR>
<TD>SkipDtdLoading
<TD>Skip loading the document's DTD.
<TR>
<TD>Validate
<TD>Validate the document against it's DTD.
<TR>
<TD>NoNetEntities
<TD>Do not use the Internet to fetch DTD's or entities.
<TR>
<TD>WarnNetEntities
<TD>Output notification when DTD's or entities are fetched over the Internet.
Not implemented yet.
<TR>
<TD>Verbose
<TD>Output each step taken by XSLT in processing the stylesheet and the document
in the server debug log. Debug logging must be enabled in addition.
<TR>
<TD>XInclude
<TD>Process the input document using the Xinclude specification. More details on
this can be found in the Xinclude specification: http://www.w3.org/TR/xinclude/
<TR>
<TD>SgmlCatalogs
<TD>Use catalogs to resolve the location of external entities. This speeds DTD resolution.
By having a catalog file point to a local version of the DTD, XSLT does not have to use
the Internet to fetch the DTD. XSLT uses the catalog identified by the environmental
variable SGML_CATALOG_FILES.
<TR>
<TD>Html
<TD>The input document is an HTML file.
<TR>
<TD>Docbook
<TD>The input document is DocBook SGML. This is not to be used for DocBook XML documents.
<TR>
<TD>Timing
<TD>Display the time used for parsing the stylesheet, parsing the document and applying
the stylesheet and saving the result. Displayed in milliseconds. Not implemented yet.
<TR>
<TD>Profile
<TD>Output profiling information detailing the amount of time spent in each part of the
stylesheet. This is useful in optimizing stylesheet performance. Not implemented yet.
<TR>
<TD>Debug
<TD>Output an XML tree of the transformed document for debugging purposes on STDOUT.
</TABLE>
</CENTER>
Multiple options may be listed together by seperating them using the pipe
('|') character. Whitespace will be stripped from the option pattern. Options
are matched without regard to case sensitivity. Unknown options will raise
a configuration error. The option directive may be repeated multiple times.
Notes:
Some of the configuration options are not reentrant. None of the options are applied,
when the DefaultStylesheet is loaded at server startup. Embedded stylesheets work
only with enabled option "Validate", which is probably a bug in libxml2 (2.4.20).
The libxml 2 has been compiled _REENTRANT and with some minor changes. Thus other
binary distribution of libxml2 might not work with Pi3Web.
The Content-Type for the output is automatic detected, if possible. Otherwise the
parameter "DefaultContentType" or the default Content-Type of the server is used.
For POST requests the received form data must be of Content-Type "text/plain"
or "application/x-www-form-urlencoded". The received form is converted into a
generic XML format, which follows this simple DTD -
<PRE>
<!DOCTYPE form [
<!ELEMENT form (field+)>
<!ELEMENT field #PCDATA>
<!ATTLIST field name NMTOKEN #REQUIRED>
]
>
</PRE>
Phase:
HANDLE
Returns:
PIAPI_COMPLETED, PIAPI_ERROR, or INT_REDIRECT accordingly
to the status returned by the handler.
Example:
<PRE>
<Object>
Name XSLT
Class XSLTClass
</Object>
<Object>
...
Handle Condition="&cmp(&dblookup(response,string,ObjectMap,XSLT),XSLT)" \
XSLT
...
</Object>
</PRE>
/*___+++HTMLDOC_END+++___*/
#endif
#define STATE_NEW 0
#define STATE_STARTSTREAM 1
#define STATE_ENDSTREAM 2
#define STATE_END 3
#define START_FORM "<?xml version=\"1.0\"?>\r\n<form>\r\n"
#define END_FORM "</form>\r\n"
#define START_FIELD_A "\t<field name=\""
#define START_FIELD_B "\">"
#define END_FIELD "</field>\r\n"
typedef struct {
PIIOBuffer *iobuf;
long clength;
long read;
int state;
} in_ctx;
/*____________________________________________________________________________*\
*
Description: Callback hook to read POST form of type text/plain
\*____________________________________________________________________________*/
static int xmlReadPlainCB (void *context, char *buffer, int len) {
in_ctx *ctx = (in_ctx *)context;
// new document
if (ctx->state == STATE_NEW) {
strcpy(buffer, START_FORM);
ctx->state = STATE_STARTSTREAM;
return strlen(START_FORM);
};
// end document
if (ctx->state == STATE_END) {
return 0;
};
// end stream
if (ctx->state == STATE_ENDSTREAM) {
strcpy(buffer, END_FORM);
ctx->state = STATE_END;
return strlen(END_FORM);
}
int iRet = len < ctx->clength - ctx->read ? len : ctx->clength - ctx->read;
const char *inbuf = PIIOBuffer_read( ctx->iobuf, &iRet );
if (iRet) {
char *outbuf = buffer;
char *pValue = (char *)inbuf;
pValue[iRet] = '\0';
StringTokenizer tTokens( inbuf, "\r", iRet );
for(int i=0; i<tTokens.NumTokens(); i++)
{
const char *pToken = tTokens.GetToken( i );
if (*pToken == '\n') pToken++;
pValue = strchr(pToken, '=');
if (pValue)
{
pValue++;
// not in 1st form field!
if (ctx->read||outbuf-buffer) {
strcpy(outbuf, END_FIELD);
outbuf += strlen(END_FIELD);
}
strcpy(outbuf, START_FIELD_A);
outbuf += strlen(START_FIELD_A);
strncpy(outbuf, pToken, (pValue-pToken)-1);
outbuf += (pValue-pToken)-1;
strcpy(outbuf, START_FIELD_B);
outbuf += strlen(START_FIELD_B);
strcpy(outbuf, pValue);
outbuf += strlen(pValue);
}
else
{
strcpy(outbuf, pToken);
outbuf += strlen(pToken);
}
}
ctx->read += iRet;
// last form field
if (ctx->read == ctx->clength) {
strcpy(outbuf, END_FIELD);
outbuf += strlen(END_FIELD);
ctx->state = STATE_ENDSTREAM;
}
return outbuf - buffer;
};
return 0;
}
/*____________________________________________________________________________*\
*
Description: Callback hook to read POST form of type
application/x-www-form-urlencoded
\*____________________________________________________________________________*/
static int xmlReadFormCB (void *context, char *buffer, int len) {
in_ctx *ctx = (in_ctx *)context;
// new document
if (ctx->state == STATE_NEW) {
strcpy(buffer, START_FORM);
ctx->state = STATE_STARTSTREAM;
return strlen(START_FORM);
};
// end document
if (ctx->state == STATE_END) {
return 0;
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -