예제 #1
0
  /* Taken from libxml2, xmlSAXParseMemoryWithData */
xmlDocPtr mxslt_doc_xml_load_entity(mxslt_doc_t * document, char * localfile) {
  xmlParserCtxtPtr ctx;
  xmlParserInputPtr input;
  xmlDocPtr retval;
  xmlChar * filename;

  mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML | MXSLT_DBG_DEBUG | MXSLT_DBG_VERBOSE0,
		"load_entity/xmlCreateMemoryParserCtxt -- replacing entities: %08x\n", xmlSubstituteEntitiesDefaultValue);

    /* SNIPPET: This is a good mix&shake of 
     * xmlCreateMemoryParserCtxt, xmlCreateFileParserCtxt */
  ctx=xmlNewParserCtxt();
  if(ctx == NULL)
    return NULL;

#if LIBXML_VERSION >= 20600
  xmlCtxtUseOptions(ctx, MXSLT_XSLT_OPTIONS);
#endif

    /* Remember which document we are parsing
     * in this context */
  /* ctx->_private=document; */

  filename=xmlCanonicPath((xmlChar *)localfile);
  if(filename == NULL) {
    xmlFreeParserCtxt(ctx);
    return NULL;
  }
  
  input=xmlLoadExternalEntity((char *)filename, NULL, ctx);
  xmlFree(filename);
  if(input == NULL) {
    xmlFreeParserCtxt(ctx);
    return NULL;
  }

  inputPush(ctx, input);

  if(ctx->directory == NULL)
    ctx->directory=xmlParserGetDirectory(localfile);
    /* END SNIPPET */

  /* MXSLT_DUMP_CTX(ctx); */

    /* Parse document */
  xmlParseDocument(ctx);

  if(ctx->wellFormed)
    retval=ctx->myDoc;
  else {
    retval=NULL;
    xmlFreeDoc(ctx->myDoc);
    ctx->myDoc=NULL;
  }
  xmlFreeParserCtxt(ctx);

  return retval;
}
예제 #2
0
bool HHVM_METHOD(XMLReader, XML,
                 const String& source,
                 const Variant& encoding /*= null_variant*/,
                 int64_t options /*= 0*/) {
  auto* data = Native::data<XMLReader>(this_);
  const String& str_encoding = encoding.isNull()
                            ? null_string
                            : encoding.toString();
  xmlParserInputBufferPtr inputbfr = xmlParserInputBufferCreateMem(
    source.c_str(), source.size(), XML_CHAR_ENCODING_NONE);

  if (inputbfr != nullptr) {
    char *uri = nullptr;
    String directory = g_context->getCwd();
    if (!directory.empty()) {
      if (directory[directory.size() - 1] != '/') {
        directory += "/";
      }
      uri = (char *) xmlCanonicPath((const xmlChar *) directory.c_str());
    }

    xmlTextReaderPtr reader = xmlNewTextReader(inputbfr, uri);

    if (reader != nullptr) {
      int ret = 0;
#if LIBXML_VERSION >= 20628
      ret = xmlTextReaderSetup(reader, nullptr, uri, str_encoding.data(),
                               options);
#endif
      if (ret == 0) {
        data->m_ptr = reader;
        data->m_input = inputbfr;

        if (uri) {
          xmlFree(uri);
        }

        return true;
      }
    }

    if (uri) {
      xmlFree(uri);
    }
  }

  if (inputbfr) {
    xmlFreeParserInputBuffer(inputbfr);
  }

  raise_warning("Unable to load source data");
  return false;
}
예제 #3
0
bool c_XMLReader::t_xml(const String& source, const String& encoding /*= null_string*/, int64_t options /*= 0*/) {
  xmlParserInputBufferPtr inputbfr = xmlParserInputBufferCreateMem(source.c_str(), source.size(), XML_CHAR_ENCODING_NONE);

  if (inputbfr != NULL) {
    char *uri = NULL;
    String directory = g_context->getCwd();
    if (!directory.empty()) {
      if (directory[directory.size() - 1] != '/') {
        directory += "/";
      }
      uri = (char *) xmlCanonicPath((const xmlChar *) directory.c_str());
    }

    xmlTextReaderPtr reader = xmlNewTextReader(inputbfr, uri);

    if (reader != NULL) {
      int ret = 0;
#if LIBXML_VERSION >= 20628
      ret = xmlTextReaderSetup(reader, NULL, uri, encoding.data(), options);
#endif
      if (ret == 0) {
        m_ptr = reader;
        m_input = inputbfr;

        if (uri) {
          xmlFree(uri);
        }

        return true;
      }
    }

    if (uri) {
      xmlFree(uri);
    }
  }

  if (inputbfr) {
    xmlFreeParserInputBuffer(inputbfr);
  }

  raise_warning("Unable to load source data");
  return false;
}
예제 #4
0
bool c_XMLReader::t_xml(CStrRef source, CStrRef encoding /*= null_string*/, int64 options /*= 0*/) {
  INSTANCE_METHOD_INJECTION_BUILTIN(XMLReader, XMLReader::xml);
  xmlParserInputBufferPtr inputbfr = xmlParserInputBufferCreateMem(source.c_str(), source.size(), XML_CHAR_ENCODING_NONE);

  if (inputbfr != NULL) {
    char *uri = NULL;
    String directory = g_context->getCwd();
    if (!directory.empty()) {
      if (directory[directory.size() - 1] != '/') {
        directory += '/';
      }
      uri = (char *) xmlCanonicPath((const xmlChar *) directory.c_str());
    }

    xmlTextReaderPtr reader = xmlNewTextReader(inputbfr, uri);

    if (reader != NULL) {
      int ret = xmlTextReaderSetup(reader, NULL, uri, encoding.data(), options);
      if (ret == 0) {
        m_ptr = reader;
        m_input = inputbfr;

        if (uri) {
          xmlFree(uri);
        }

        return true;
      }
    }

    if (uri) {
      xmlFree(uri);
    }
  }

  if (inputbfr) {
    xmlFreeParserInputBuffer(inputbfr);
  }

  raise_warning("Unable to load source data");
  return false;
}
예제 #5
0
/* {{{ proto boolean XMLReader::XML(string source [, string encoding [, int options]])
Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader, XML)
{
	zval *id;
	size_t source_len = 0, encoding_len = 0;
	zend_long options = 0;
	xmlreader_object *intern = NULL;
	char *source, *uri = NULL, *encoding = NULL;
	int resolved_path_len, ret = 0;
	char *directory=NULL, resolved_path[MAXPATHLEN];
	xmlParserInputBufferPtr inputbfr;
	xmlTextReaderPtr reader;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
		return;
	}

	id = getThis();
	if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry)) {
		id = NULL;
	}
	if (id != NULL) {
		intern = Z_XMLREADER_P(id);
		xmlreader_free_resources(intern);
	}

	if (!source_len) {
		php_error_docref(NULL, E_WARNING, "Empty string supplied as input");
		RETURN_FALSE;
	}

	inputbfr = xmlParserInputBufferCreateMem(source, source_len, XML_CHAR_ENCODING_NONE);

    if (inputbfr != NULL) {
/* Get the URI of the current script so that we can set the base directory in libxml */
#if HAVE_GETCWD
		directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
#elif HAVE_GETWD
		directory = VCWD_GETWD(resolved_path);
#endif
		if (directory) {
			resolved_path_len = strlen(resolved_path);
			if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
				resolved_path[resolved_path_len] = DEFAULT_SLASH;
				resolved_path[++resolved_path_len] = '\0';
			}
			uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
		}
		reader = xmlNewTextReader(inputbfr, uri);

		if (reader != NULL) {
#if LIBXML_VERSION >= 20628
			ret = xmlTextReaderSetup(reader, NULL, uri, encoding, options);
#endif
			if (ret == 0) {
				if (id == NULL) {
					object_init_ex(return_value, xmlreader_class_entry);
					intern = Z_XMLREADER_P(return_value);
				} else {
					RETVAL_TRUE;
				}
				intern->input = inputbfr;
				intern->ptr = reader;

				if (uri) {
					xmlFree(uri);
				}

				return;
			}
		}
	}

	if (uri) {
		xmlFree(uri);
	}

	if (inputbfr) {
		xmlFreeParserInputBuffer(inputbfr);
	}
	php_error_docref(NULL, E_WARNING, "Unable to load source data");
	RETURN_FALSE;
}
예제 #6
0
  /* Taken from libxml2, xmlSAXParseMemoryWithData */
xmlDocPtr mxslt_doc_xml_parse(mxslt_doc_t * document, xmlParserInputBufferPtr buf, char * localfile) {
  xmlParserCtxtPtr ctx;
  xmlParserInputPtr input;
  xmlDocPtr retval;

  mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML | MXSLT_DBG_DEBUG | MXSLT_DBG_VERBOSE0,
		"xml_parse/xmlCreateMemoryParserCtxt -- replacing entities: %08x\n", xmlSubstituteEntitiesDefaultValue);

  if(buf == NULL)
    return NULL;

    /* SNIPPET: This is a good mix&shake of 
     * xmlCreateMemoryParserCtxt, xmlCreateFileParserCtxt */
  ctx=xmlNewParserCtxt();
  if(ctx == NULL) {
    xmlFreeParserInputBuffer(buf);
    return NULL;
  }

#if LIBXML_VERSION >= 20600
  xmlCtxtUseOptions(ctx, MXSLT_XSLT_OPTIONS);
#endif

    /* Default are no longer changed... since 2.6.0 they
     * are completely ignored, leading to broken modxslt :|| */
  if(ctx->sax) {
    ctx->sax->resolveEntity=mxslt_sax_resolve_entity;
    ctx->sax->processingInstruction=mxslt_sax_processing_instruction;
  }

    /* Remember which document we are parsing
     * in this context */
/*  ctx->_private=document; */

  input=xmlNewInputStream(ctx);
  if(input == NULL) {
    xmlFreeParserInputBuffer(buf);
    xmlFreeParserCtxt(ctx);

    return NULL;
  }

  input->filename=(char *)xmlCanonicPath((xmlChar *)localfile);
  if(input->filename == NULL) {
    xmlFreeParserCtxt(ctx);
    xmlFreeParserInputBuffer(buf);
    xmlFreeInputStream(input);

    return NULL;
  }

  input->buf=buf;
#if LIBXML_VERSION < 20900
  input->base=input->buf->buffer->content;
  input->cur=input->buf->buffer->content;
  input->end=&input->buf->buffer->content[input->buf->buffer->use];
#else
    /* With libxml2 2.9.0, the buffer struct can only be accessed through
     * methods. */
  input->base=xmlBufContent(input->buf->buffer);
  input->cur=xmlBufContent(input->buf->buffer);
  input->end=xmlBufEnd(input->buf->buffer);
#endif

  inputPush(ctx, input);

  if(ctx->directory == NULL)
    ctx->directory=xmlParserGetDirectory(localfile);
    /* END SNIPPET */

  if(mxslt_doc_debug_level(document, MXSLT_DBG_LIBXML | MXSLT_DBG_DEBUG | MXSLT_DBG_VERBOSE2)) 
    mxslt_doc_dump_ctx(ctx, document);

    /* Parse document */
  xmlParseDocument(ctx);

  if(ctx->wellFormed)
    retval=ctx->myDoc;
  else {
    retval=NULL;
    xmlFreeDoc(ctx->myDoc);
    ctx->myDoc=NULL;
  }
  xmlFreeParserCtxt(ctx);
  /* xmlFreeParserInputBuffer(buf); */

  return retval;
}
예제 #7
0
  /* This function replaces processingInstruction */
void mxslt_sax_processing_instruction(void * ctx, const xmlChar * target, const xmlChar * data) {
  xmlParserCtxtPtr ctxt=(xmlParserCtxtPtr)ctx;
  mxslt_doc_t * document=(mxslt_get_state()->document);
  mxslt_pi_style_t * style_pi;
  mxslt_pi_param_t * param_pi;
  mxslt_pi_base_t * base_pi;
  char * type = NULL, * tmp;
  xmlNodePtr pi;
  int status;

    /* WARNING: don't change this array! Look below! */
  static const mxslt_attr_search_t xml_stylesheet[] = {
    { (xmlChar *)"href", mxslt_sizeof_str("href") },
    { (xmlChar *)"media", mxslt_sizeof_str("media") },
    { (xmlChar *)"type", mxslt_sizeof_str("type") }
  };

    /* WARNING: don't change this array! Look below! */
  static const mxslt_attr_search_t mxslt_param[] = {
    { (xmlChar *)"name", mxslt_sizeof_str("name") },
    { (xmlChar *)"value", mxslt_sizeof_str("value") }
  };

    /* WARNING: don't change this array! Look below! */
  static const mxslt_attr_search_t mxslt_base[] = {
    { (xmlChar *)"value", mxslt_sizeof_str("value") }
  };

    /* This array _must_ have the same number of elements
     * as the array  xml_stylesheet */
  char * xml_stylesheet_values[] = { NULL, NULL, NULL };
  enum xml_stylesheet_types {
    t_href=0,
    t_media,
    t_type
  };

    /* This array _must_ have the same number of elements
     * as the array  mxslt_param */
  char * mxslt_param_values[] = { NULL, NULL };
  enum mxslt_param_types {
    t_name=0,
    t_select
  };

    /* This array _must_ have the same number of elements 
     * as the array mxslt_base */
  char * mxslt_base_values[] = { NULL };
  enum mxslt_base_types {
    t_value=0
  };

  mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML, "processing instruction \"%s\", attributes |%s|\n", target, data);

    /* Ignore pi when we're parsing the stylesheet */
  if(document->flags & MXSLT_STYLE)
    return;

    /* Create a new pi node */
  pi=xmlNewPI(target, data);
  if(!pi)
    return;

    /* Check if target is a known pi */
  switch(target[0]) {
    case 'x':
      if(!xmlStrEqual(target+1, (xmlChar *)"xml-stylesheet"+1))
        break;

        /* Get href, type and media from attribute list */
      status=mxslt_get_static_attr((char *)data, xml_stylesheet, xml_stylesheet_values, mxslt_sizeof_array(xml_stylesheet));
      if(status != MXSLT_OK) {
	if(xml_stylesheet_values[0])
	  xfree(xml_stylesheet_values[0]);
	if(xml_stylesheet_values[1])
	  xfree(xml_stylesheet_values[1]);
	if(xml_stylesheet_values[2])
	  xfree(xml_stylesheet_values[2]);
	goto error;
      }

      if(xml_stylesheet_values[t_type] && xml_stylesheet_values[t_href]) {
	  /* Decode type */
	type=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_type], 
					     XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0);

          /* Skip blanks before type */
        for(tmp=type; MXSLT_IS_BLANK(*tmp); tmp++)
          ;

          /* compare type string */
        if(!strncmp(tmp, "text/xml", mxslt_sizeof_str("text/xml")) || 
           !strncmp(tmp, "text/xsl", mxslt_sizeof_str("text/xsl"))) {

            /* trailing spaces are allowed */
          for(tmp+=mxslt_sizeof_str("text/x?l"); MXSLT_IS_BLANK(*tmp); tmp++)
            ;

	    /* Check there's nothing else beside them */
          if(*tmp != '\0') {
	    xmlFree(type);
  	    break;
	  }
	    
	    /* Type is ok, add parameter to processing 
	     * instruction */
	  style_pi=(mxslt_pi_style_t *)xmalloc(sizeof(mxslt_pi_style_t));
	  style_pi->type=MXSLT_PI_STDST;
	  style_pi->ctype=type;
	  style_pi->href=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_href], 
					       XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0);
	  if(xml_stylesheet_values[t_media])
	    style_pi->media=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_media],
					        XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0);
	  else
	    style_pi->media=NULL;

	    /* tie up xmlNode and style_pi */
	  XML_LINK_PI(document, pi, style_pi);
	} else {
	  mxslt_error(document, "warning - <xml-stylesheet type=\"... unknown: '%s'!\n", type);
	  xmlFree(type);
	}
      } else {
	if(!xml_stylesheet_values[t_href])
	  mxslt_error(document, "warning - <xml-stylesheet href=\"... is missing, skipping PI!\n");
	if(!xml_stylesheet_values[t_type])
	  mxslt_error(document, "warning - <xml-stylesheet type=\"... is missing, skipping PI!\n");
      }

      if(xml_stylesheet_values[t_media])
        xfree(xml_stylesheet_values[t_media]);
      if(xml_stylesheet_values[t_href])
        xfree(xml_stylesheet_values[t_href]);
      if(xml_stylesheet_values[t_type])
        xfree(xml_stylesheet_values[t_type]);
      break;

    case 'm':
      if(target[1] != 'o' || target[2] != 'd' || 
         target[3] != 'x' || target[4] != 's' || 
         target[5] != 'l' || target[6] != 't' ||
	 target[7] != '-') 
        break;
          
      switch(target[8]) {
	case 'b':
	  if(!xmlStrEqual(target+8, (xmlChar *)"modxslt-base"+8)) {
            mxslt_error(document, "warning - unknown modxslt PI: %s in %s\n", target, document->localfile);
            break;
	  }

	    /* Read modxslt-base */
          status=mxslt_get_static_attr((char *)data, mxslt_base, mxslt_base_values, mxslt_sizeof_array(mxslt_base));
	  if(status != MXSLT_OK) {
            if(mxslt_base_values[0])
              xfree(mxslt_base_values[0]);
	    goto error;
	  }

	    /* Verify we got the base */
	  if(!mxslt_base_values[0]) {
            mxslt_error(document, "warning - <modxslt-base ... base=\" is missing, skipping PI\n", target, document->localfile);
	    break;
	  }

	    /* Remember the pi we found */
	  base_pi=(mxslt_pi_base_t *)(xmalloc(sizeof(mxslt_pi_base_t)));
	  base_pi->type=MXSLT_PI_UBASE;
	  base_pi->file=(char *)xmlCanonicPath((xmlChar *)mxslt_base_values[0]);
	  base_pi->directory=xmlParserGetDirectory(mxslt_base_values[0]);
	  xfree(mxslt_base_values[0]);

	    /* Switch base in the current context */
	  if(ctxt->input->filename)
	    xmlFree((char *)ctxt->input->filename);
	  if(ctxt->directory)
	    xmlFree(ctxt->directory);

	    /* Remember those information */
	  ctxt->input->filename=(char *)xmlStrdup((xmlChar *)base_pi->file);
	  ctxt->directory=(char *)xmlStrdup((xmlChar *)base_pi->directory);

	    /* tie up xmlNode and style_pi */
	  XML_LINK_PI(document, pi, base_pi);
	  break;

        case 'p':
          if(!xmlStrEqual(target+8, (xmlChar *)"modxslt-param"+8)) {
            mxslt_error(document, "warning - unknown modxslt PI: %s in %s\n", target, document->localfile);
            break;
	  }

          status=mxslt_get_static_attr((char *)data, mxslt_param, mxslt_param_values, mxslt_sizeof_array(mxslt_param));
	  if(status != MXSLT_OK) {
	    if(mxslt_param_values[0])
	      xfree(mxslt_param_values[0]);
	    if(mxslt_param_values[1])
	      xfree(mxslt_param_values[1]);

	    goto error;
	  }

          if(mxslt_param_values[t_name]) {
	      /* Allocate and create pi */
	    param_pi=(mxslt_pi_param_t *)xmalloc(sizeof(mxslt_pi_param_t));
	    param_pi->type=MXSLT_PI_PARAM;
	    param_pi->param=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)mxslt_param_values[t_name],
					        XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0);
	    param_pi->value=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)mxslt_param_values[t_select],
					        XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0);

	      /* Link pi to list of pis */
	    XML_LINK_PI(document, pi, param_pi);
	  } else {
    	    mxslt_error(document, "warning - modxslt-param specified without ``name'' attribute in `%s'\n", document->localfile);
	  }

	    /* Free memory up */
          if(mxslt_param_values[t_select])
            xfree(mxslt_param_values[t_select]);
          if(mxslt_param_values[t_name])
            xfree(mxslt_param_values[t_name]);
          break;
    
        case 's':
          if(!xmlStrEqual(target+8, (xmlChar *)"modxslt-stylesheet"+8)) {
            mxslt_error(document, "warning - unknown modxslt PI: %s in %s\n", target, document->localfile);
            break;
	  }
      
          status=mxslt_get_static_attr((char *)data, xml_stylesheet, xml_stylesheet_values, mxslt_sizeof_array(xml_stylesheet));
	  if(status != MXSLT_OK) {
	    if(xml_stylesheet_values[0])
	      xfree(xml_stylesheet_values[0]);
	    if(xml_stylesheet_values[1])
	      xfree(xml_stylesheet_values[1]);
	    if(xml_stylesheet_values[2])
	      xfree(xml_stylesheet_values[2]);

	    goto error;
	  }

          if(xml_stylesheet_values[t_type]) {
	      /* Decode type */
  	    type=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_type], 
					         XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0);

              /* Skip blanks before type */
            for(tmp=type; MXSLT_IS_BLANK(*tmp); tmp++)
              ;

              /* compare type string */
            if(!strncmp(tmp, "text/xml", mxslt_sizeof_str("text/xml")) || 
               !strncmp(tmp, "text/xsl", mxslt_sizeof_str("text/xsl"))) {

                /* trailing spaces are allowed */
              for(tmp+=mxslt_sizeof_str("text/x?l"); MXSLT_IS_BLANK(*tmp); tmp++)
                ;

	        /* Check there's nothing else beside them */
              if(*tmp != '\0') {
	        mxslt_error(document, "warning - <modxslt-stylesheet type=\"... trailing junk: '%s'!\n", type);
        	xmlFree(type);
  	        break;
	      }
	    
	        /* Type is ok, add parameter to processing 
	         * instruction */
    	      style_pi=(mxslt_pi_style_t *)xmalloc(sizeof(mxslt_pi_style_t));
	      style_pi->type=MXSLT_PI_MODST;
	      style_pi->ctype=type;
	      if(xml_stylesheet_values[t_href])
	        style_pi->href=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_href], 
				    	        XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0);
	      else 
		style_pi->href=NULL;
     	      if(xml_stylesheet_values[t_media])
	        style_pi->media=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_media],
					        XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0);
	      else
	        style_pi->media=NULL;

	        /* Link to nodes chain */
	      XML_LINK_PI(document, pi, style_pi);
            } else {
	      mxslt_error(document, "warning - <modxslt-stylesheet type=\"... unknown: '%s'!\n", type);
	      xmlFree(type);
	    }
	  }

          if(xml_stylesheet_values[t_media])
            xfree(xml_stylesheet_values[t_media]);
          if(xml_stylesheet_values[t_href])
            xfree(xml_stylesheet_values[t_href]);
          if(xml_stylesheet_values[t_type])
            xfree(xml_stylesheet_values[t_type]);
          break;

        default:
          mxslt_error(document, "warning - unknown modxslt PI: %s in %s\n", target, document->localfile);
          break;
      }
      break;
  }      

    /* Taken from `processingInstruction' */
  switch(ctxt->inSubset) {
    case 1:
      xmlAddChild((xmlNodePtr)ctxt->myDoc->intSubset, pi);
      return;

    case 2:
      xmlAddChild((xmlNodePtr)ctxt->myDoc->extSubset, pi);
      return;
  }

  if(!ctxt->myDoc->children || !ctxt->node) {
    xmlAddChild((xmlNodePtr)ctxt->myDoc, pi);
    return;
  }

  if(ctxt->node->type == XML_ELEMENT_NODE)
    xmlAddChild(ctxt->node, pi);
  else 
    xmlAddSibling(ctxt->node, pi);

  return;

error:
   mxslt_error(document, "warning - weird data while processing PI: %s in %s\n", target, document->localfile);
   xmlFreeNode(pi);

   return;
}