页面内容和表现风格的分离,(XSLT)
页面内容和表现风格分离的第一步,是CSS风格文件和HTML页面的分离,但是,HTML的页面内容和显示元素还是紧紧捆绑在一起。XML推广之后,XSLT也大行其道,大量地应用在web发布系统中。ASP.Net和java web框架都在朝这个方向走,只是java web框架走得更快,更远。下面进行说明。
在处理XSLT时,SAX接口要比DOM接口快得多,而且几乎不占据内存空间。令人不安的是,.Net框架到现在还没有提供SAX接口。微软提供了一套MSXML SDK,其中包含了基于COM组件的SAX实现,并提供了在VB和VC中应用的实例。MSXML SAX的VC用例中,需要包含头文件msxml2.h。这就是说,.Net框架无法以一种自然的方式调用MSXML SAX。还有,.Net框架的XSLT是如何实现的,即,System.Xml.Xsl.XslTransform是用什么方式实现的,是调用SAX接口,还是DOM接口。如何使用.Net框架组成一条XSLT的处理管道?我也找不到方法。也没有发现这方面的例子。
Apache Xerce项目支持XML处理,提供Java和C++版本,并提供了调用MSXML的封装;Apache Xalan项目支持XSLT处理;Apache Cocoon2.0,使用SAX接口,组成XSLT的处理管道。
Apache Xalan项目的一个例子文件UseXMLFilters.java
UseXMLFilters.java。(节录,文件头部分省略)
public class UseXMLFilters
{
public static void main(String[] args)
throws TransformerException, TransformerConfigurationException,
SAXException, IOException
{
// Instantiate a TransformerFactory.
TransformerFactory tFactory = TransformerFactory.newInstance();
// Determine whether the TransformerFactory supports The use uf SAXSource
// and SAXResult
if (tFactory.getFeature(SAXSource.FEATURE) && tFactory.getFeature(SAXResult.FEATURE))
{
// Cast the TransformerFactory to SAXTransformerFactory.
SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) tFactory);
// Create an XMLFilter for each stylesheet.
XMLFilter xmlFilter1 = saxTFactory.newXMLFilter(new StreamSource("foo1.xsl"));
XMLFilter xmlFilter2 = saxTFactory.newXMLFilter(new StreamSource("foo2.xsl"));
XMLFilter xmlFilter3 = saxTFactory.newXMLFilter(new StreamSource("foo3.xsl"));
// Create an XMLReader.
XMLReader reader = XMLReaderFactory.createXMLReader();
// xmlFilter1 uses the XMLReader as its reader.
xmlFilter1.setParent(reader);
// xmlFilter2 uses xmlFilter1 as its reader.
xmlFilter2.setParent(xmlFilter1);
// xmlFilter3 uses xmlFilter2 as its reader.
xmlFilter3.setParent(xmlFilter2);
// xmlFilter3 outputs SAX events to the serializer.
Serializer serializer = SerializerFactory.getSerializer
(OutputProperties.getDefaultMethodProperties("xml"));
serializer.setOutputStream(System.out);
xmlFilter3.setContentHandler(serializer.asContentHandler());
// Perform the series of transformations as follows:
// - transformer3 gets its parent (transformer2) as the XMLReader/XMLFilter
// and calls transformer2.parse(new InputSource("foo.xml")).
// - transformer2 gets its parent (transformer1) as the XMLReader/XMLFilter
// and calls transformer1.parse(new InputSource("foo.xml")).
// - transformer1 gets its parent (reader, a SAXParser) as the XMLReader
// and calls reader.parse(new InputSource("foo.xml")).
// - reader parses the XML document and sends the SAX parse events to transformer1,
// which performs transformation 1 and sends the output to transformer2.
// - transformer2 parses the transformation 1 output, performs transformation 2, and
// sends the output to transformer3.
// - transformer3 parses the transformation 2 output, performs transformation 3,
// and sends the output to the serializer.
xmlFilter3.parse(new InputSource("foo.xml"));
}
}
}
Apache Cocoon项目的一个配置文件例子sitemap.xmap
Apache Cocoon项目的sitemap.xmap定义了XSLT处理管道。见下例中的<map:handle-errors>部分,错误信息经过两次XSLT处理," error2document.xsl" 和"apache.xsl"。
/sample/tutorial/sitemap.xmap (节录,无关部分省略)
…
<map:pipelines>
<map:pipeline>
<map:match pattern="*-dept.xml">
<map:act set="process">
<map:parameter name="descriptor" value="context://tutorial/docs/department-form.xml"/>
<map:generate type="serverpages" src="docs/confirm-dept.xsp"/>
<map:serialize type="xml"/>
</map:act>
<map:generate type="serverpages" src="docs/{1}-dept.xsp"/>
<map:serialize type="xml"/>
</map:match>
...
<map:handle-errors>
<map:transform src="stylesheets/system/error2document.xsl"/>
<map:transform src="stylesheets/apache.xsl"/>
<map:serialize status-code="500"/>
</map:handle-errors>
</map:pipeline>
...
</map:pipelines>
ASP.Net的Xml Web控件例子
下面的示例从.Net框架文当中摘录,说明如何使用 Xml 控件通过示例 XSL 转换文件来显示示例 XML 文件。示例 XML 文件名为 People.xml,示例 XSL 转换文件名为 Peopletable. xsl。可以看到,asp:Xml控间只能进行一步XSLT转换。
<html>
<body>
<h3>Xml Example</h3>
<form runat="server">
<asp:Xml id="xml1"
DocumentSource="people.xml"
TransformSource="peopletable.xsl"
runat="server" />
</form>
</body>
</html>