Personal tools


Extension:XmlOutput.php

From OrganicDesign

Jump to: navigation, search
<?php
# Extension:XmlOutput
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
# - Author: [http://www.organicdesign.co.nz/nad User:Nad]
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
 
define('XMLOUTPUT_VERSION','1.0.0, 2007-09-10');
 
$wgXmlOutputTitle = 'XML'; # Name of the special page used to return articles as raw XML
 
$wgExtensionFunctions[] = 'wfSetupXmlOutput';
 
$wgExtensionCredits['specialpage'][] = array(
	'name'        => 'Special:XmlOutput',
	'author'      => '[http://www.organicdesign.co.nz/nad User:Nad]',
	'description' => 'Allows articles containing XML to be returned as raw XML with associated XSLT applied if required.',
	'url'         => 'http://www.mediawiki.org/wiki/Extension:XmlOutput',
	'version'     => XMLOUTPUT_VERSION
);
 
# Add an XML action if the content is XML
$wgHooks['ParserBeforeStrip'][] = 'wfXmlOutputAddActionTest';
function wfXmlOutputAddActionTest(&$parser,&$text) {
	global $wgHooks;
	if (preg_match('/<\\?xml/',$text)) $wgHooks['SkinTemplateTabs'][] = 'wfXmlOutputAddAction';
	return true;
}
 
function wfXmlOutputAddAction(&$skin,&$actions) {
	global $wgTitle,$wgXmlOutputTitle;
	if (is_object($wgTitle)) {
		$url = Title::makeTitle(NS_SPECIAL,$wgXmlOutputTitle);
		$url = $url->getLocalUrl().'/'.$wgTitle->getPrefixedText();
		$actions[$wgXmlOutputTitle] = array('text' => 'xml', 'class' => false, 'href' => $url);
	}
	return true;
}
 
# Define a new class based on the SpecialPage class
require_once "$IP/includes/SpecialPage.php";
class SpecialXmlOutput extends SpecialPage {
 
	var $xslt = array();
 
	# Constructor
	function SpecialXmlOutput() {
		global $wgXmlOutputTitle;
		SpecialPage::SpecialPage($wgXmlOutputTitle,'',false,false,false,false);
		}
 
	# Override SpecialPage::execute()
	# - $param is from the URL, eg Special:XmlOutput/param
	function execute($param) {
		global $wgParser,$wgUser;
		$wgParser->disableCache();
		$this->setHeaders();
 
		# Get article content and expand any templates
		$title = Title::newFromText($param);
		$xml   = new Article($title);
		$xml   = preg_replace('/\{\{.+?\}\}/s','',$xml->getContent());
 
		# Extract all the XSLT's referred to in the XML and remove/record them
		$xml = preg_replace_callback(
			'/<\\?xml-stylesheet\\s+type="text\\/xsl"\\s+href="(.+?)"\\?>/s',
			array($this,'extractXSLT'),
			$xml
		);
 
		# Convert the XML to a DOM object
		$doc = new DOMDocument();
		$doc->loadXML($xml);
 
		# Apply extracted XSLT's to the DOM object
		foreach ($this->xslt as $title) {
			$title = Title::newFromText($title);
			if ($title->exists()) {
				$xslt = new Article($title);
				$xslt = preg_replace('/\{\{.+?\}\}/s','',$xslt->getContent());
				$xsl  = new DOMDocument();
				$xsl->loadXML($xslt);
				$proc = new XSLTProcessor;
				$proc->importStyleSheet($xsl);
				$doc  = $proc->transformToDoc($doc);
			}
		}
 
		# Return to the client as raw XML text
		$xml = $doc->saveXML();
		while(@ob_end_clean());
		header('Content-Type: application/xml');
		if (in_array('Content-Encoding: gzip',headers_list())) $xml = gzencode($xml);
		echo($xml);
		die;
	}
 
	# Extract XSLT's from the XML and record/remove them
	function extractXSLT($match) {
		$this->xslt[] = $match[1];
		return '';
	}
}
 
# Called from $wgExtensionFunctions array when initialising extensions
function wfSetupXmlOutput() {
	global $wgLanguageCode,$wgMessageCache,$wgXmlOutputTitle;
 
	# Add the messages used by the specialpage
	if ($wgLanguageCode == 'en') {
		$wgMessageCache->addMessages(array('xmloutput' => $wgXmlOutputTitle));
	}
 
	# Add the specialpage to the environment
	SpecialPage::addPage(new SpecialXmlOutput());
}