j2ee —— 第 7 章 extensible stylesheet language transformations (xslt)
Post on 27-Dec-2015
250 Views
Preview:
TRANSCRIPT
J2EE—— 第 7 章 Extensible Stylesheet Language Transformations (XSL
T)
XSL 、 XSLT 和 XPath 简介 XSL-FO: 字体大小、页面布局、对象显示 XSLT: 从 XML 到某种其它格式的转换 XPath: 指定通向某个元素的路径 javax.xml.transform javax.xml.transform.dom javax.xml.transform.sax javax.xml.transform.stream
XPath 如何工作 XPath 规范定义了一个抽象文档模型,该
文档模型定义了几种类型的节点: Root, Element,Text, Attribute,Comment Processing instruction, Namespace
XSLT/XPath 数据模型 : 包含各种节点的树<xsl:template match="//LIST"> ... </xsl:template>
基本 XPath 寻址 正斜杠 (/) 用作路径分隔符 从文档的根开始的绝对路径以 / 开始 从指定位置开始的相对路径可以以任何
其它符号开始 双句点 (..) 表示当前节点的父节点 单句点 (.) 表示当前节点
基本 XPath 表达式 PROJECT[.=“MyProject”] PROJECT[STATUS] PROJECT[STATUS=“Critical”] LIST[@type=“ordered”][3] LIST[3][@type=“ordered”] * 匹配任何 Element 节点 node() 匹配任何类型的任何节点 @* 匹配任何属性节点 /HEAD/LIST//PARA
XPath 数据类型和运算符
元素的字符串值<PARA>This paragraph contains a <B>bold</B>
word</PARA> PARA/text() This paragraph contains a bold word
XPath 函数 节点集函数
id(…) 位置函数
last() :如 /HEAD[last()] position() :如 /HEAD[position()<=5] count(…) :如 /HEAD[count(HEAD)=0]
字符串函数 concat(string, string, ...): contains(string1, string2 substring-before(string1, string2) substring-after(string1, string2) substring(string, idx) substring(string, idx, len) string-length() string-length(string) normalize-space() normalize-space(string) translate(string1, string2, string3):
其它函数 Boolean 函数
not(...) true() false() lang(string)
数值函数 sum(…) floor(N) ceiling(N) round(N)
其它函数 转换函数
string(…) boolean(…) number(…)
名称空间函数 local-name(), local-name(…) namespace-uri(), namespace-uri(..) name(), name(…)
把 DOM 作为 XML 文件写出import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory;import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerConfigurationExceptio
n; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult;
TransformerFactory tFactory =TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer(); DOMSource source = new DOMSource(document);StreamResult result = new StreamResult(System.out);transformer.transform(source, result);
写出 DOM 的子树import org.w3c.dom.Node;import org.w3c.dom.NodeList;NodeList list = document.getElementsByTagName("sl
ide");Node node = list.item(0);DOMSource source = new DOMSource(node);
<?xml version="1.0" encoding="UTF-8"?> <slide type="all">
<title>Wake up to WonderWidgets!</title> </slide>
从任一数据结构生成 XMLxmozillanickname: Fredmail: Fred@barneys.housexmozillausehtmlmail: TRUEgivenname: Fredsn: Flintstonetelephonenumber: 999-Quarryhomephone: 999-BedrockLanefacsimiletelephonenumber: 888-Squawkpagerphone: 777-pagercellphone: 555-cell
准备工作import org.xml.sax.*;import org.xml.sax.helpers.AttributesImpl;public class AddressBookReader implements XMLReader {
ContentHandler handler; String nsu = ""; // NamespaceURIAttributes atts = new AttributesImpl(); String rootElement = "addressbook"; String indent = "\n "; // for readability! public void parse (InputSource input) throws IOException, SAXExcepti
on{java.io.Reader r = input.getCharacterStream(); BufferedReader br = new BufferedReader(r);
生成 SAX 事件if (handler==null) {
throw new SAXException("No content handler"); } handler.startDocument(); handler.startElement(nsu, rootElement, rootElement, atts); output("nickname", "xmozillanickname", line);line = br.readLine();...output("cell", "cellphone", line);handler.ignorableWhitespace("\n".toCharArray(), 0, 1); handler.endElement(nsu, rootElement, rootElement);handler.endDocument();
元素 SAX 事件void output(String name, String prefix, String line) throws SAXExceptio
n {int startIndex = prefix.length() + 2; // 2=length of ": " String text = line.substring(startIndex); int textLength = line.length() - startIndex; handler.ignorableWhitespace(indent.toCharArray(), 0, indent.lengt
h());handler.startElement(nsu, name, name /*"qName"*/, atts); handler.characters(text.toCharArray(), startIndex, textLength);handler.endElement(nsu, name, name);
}
把解析器用作 SAXSourceimport org.xml.sax.ContentHandler;import org.xml.sax.InputSource;import javax.xml.transform.sax.SAXSource; AddressBookReader saxReader = new AddressBookReader(); Transformer transformer = tFactory.newTransformer();FileReader fr = new FileReader(f);BufferedReader br = new BufferedReader(fr);InputSource inputSource = new InputSource(br);SAXSource source = new SAXSource(saxReader, inputSource);StreamResult result = new StreamResult(System.out);transformer.transform(source, result);
用 XSLT 转换 XML 数据<?xml version="1.0"?> <ARTICLE>
<TITLE>A Sample Article</TITLE><SECT>The First Major Section
<PARA>This section will introduce a subsection.</PARA>
<SECT>The Subsection Heading<PARA>This is the text of the subsection. </PARA>
</SECT></SECT>
</ARTICLE>
编写 XSLT 转换<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="1.0">
<xsl:output method="html"/><xsl:template match="/"> <html><body>
<xsl:apply-templates/> </body></html> </xsl:template> …
</xsl:stylesheet> 使用 html 输出方式时 , < 将输出为 <
处理 <TITLE> 和 <SECT><xsl:template match="/ARTICLE/TITLE">
<h1 align="center"><xsl:apply-templates/></h1> </xsl:template> <xsl:template match="/ARTICLE/SECT">
<h2><xsl:apply-templates select="text()|B|I|U|DEF|LINK"/></h2> <xsl:apply-templates select="SECT|PARA|LIST|NOTE"/>
</xsl:template> <xsl:template match="/ARTICLE/SECT/SECT">
<h3><xsl:apply-templates select="text()|B|I|U|DEF|LINK"/></h3> <xsl:apply-templates select="SECT|PARA|LIST|NOTE"/>
</xsl:template></xsl:stylesheet>
处理过深嵌套错误和 <PARA><xsl:template match="/ARTICLE/SECT/SECT/SECT">
<xsl:message terminate="yes">Error: Sections can only be nested 2 deep.</xsl:message>
</xsl:template><xsl:template match="PARA">
<p><xsl:apply-templates/></p></xsl:template></xsl:stylesheet>
编写基本的程序import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamResult;File stylesheet = new File(argv[0]);File datafile = new File(argv[1]);DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.parse(datafile); StreamSource stylesource = new StreamSource(stylesheet); Transformer transformer = Factory.newTransformer(stylesource);DOMSource source = new DOMSource(document);StreamResult result = new StreamResult(System.out);transformer.transform(source, result);
转换结果<html><body>
<h1 align="center">A Sample Article</h1><h2>The First Major Section
</h2><p>This section will introduce a subsection.</p><h3>The Subsection Heading
</h3><p>This is the text of the subsection.
</p>
</body></html>
剪裁空白<xsl:strip-space elements="SECT"/> <xsl:template match="text()">
<xsl:value-of select="normalize-space()"/></xsl:template>
<html><body><h1 align="center">A Sample Article</h1><h2>The First Major Section</h2><p>This section will introduce a subsection.</p><h3>The Subsection Heading</h3><p>This is the text of the subsection.</p></body></html>
处理其余的结构元素<?xml version="1.0"?> <ARTICLE>
<TITLE>A Sample Article</TITLE><SECT>The First Major Section...</SECT><SECT>The Second Major Section
<PARA>This section adds a LIST and a NOTE. </PARA><PARA>Here is the LIST:
<LIST type="ordered"><ITEM>Pears</ITEM><ITEM>Grapes</ITEM>
</LIST></PARA><PARA>And here is the NOTE:
<NOTE>Don't forget to go to the hardware store on your way to the grocery!
</NOTE> </PARA>
</SECT> </ARTICLE>
修改 XSLT<xsl:template match="PARA">
<p><xsl:apply-templates select="text()|B|I|U|DEF|LINK"/></p><xsl:apply-templates select="PARA|LIST|NOTE"/>
</xsl:template><xsl:template match="LIST">
<xsl:if test="@type='ordered'"> <ol>
<xsl:apply-templates/></ol>
</xsl:if> <xsl:if test="@type='unordered'">
<ul><xsl:apply-templates/>
</ul></xsl:if>
</xsl:template></xsl:stylesheet>
处理 <ITEM> 和 <NOTE><xsl:template match="ITEM">
<li><xsl:apply-templates/> </li>
</xsl:template> <xsl:template match="NOTE">
<blockquote><b>Note:</b><br/> <xsl:apply-templates/>
</blockquote> </xsl:template> 当多个模板都匹配时,最后出现的模板优先
运行结果…<h2>The Second Major Section</h2><p>This section adds a LIST and a NOTE.</p><p>Here is the LIST:</p><ol><li>Pears</li><li>Grapes</li></ol><p>And here is the NOTE:</p><blockquote><b>Note:</b><br>Don't forget to go to the hardware store on your way to thegrocery!</blockquote>
处理内联 ( 内容 ) 元素<SECT>The <I>Third</I> Major Section
<PARA>In addition to the inline tag in the heading, this section defines the term <DEF>inline</DEF>, which literally means "no line break". It also adds a simple link to the main page for the Java platform (<LINK>http://java.sun.com</LINK>), as well as a link to the <LINK target="http://java.sun.com/xml">XML</LINK> page.
</PARA></SECT>
修改 XSLT<xsl:template match="DEF">
<i><xsl:apply-templates/></i></xsl:template>
<xsl:template match="B|I|U"><xsl:element name="{name()}"><xsl:apply-templates/></xsl:element>
</xsl:template>
处理 <LINK><xsl:template name="htmLink">
<xsl:param name="dest" select="UNDEFINED"/><xsl:element name="a">
<xsl:attribute name="href"> <xsl:value-of select="$dest"/>
</xsl:attribute><xsl:apply-templates/>
</xsl:element></xsl:template>
调用命名模板<xsl:template match="LINK">
<xsl:if test="@target"><xsl:call-template name="htmLink">
<xsl:with-param name="dest" select="@target"/></xsl:call-template></xsl:if><xsl:if test="not(@target)">
<xsl:call-template name="htmLink"><xsl:with-param name="dest">
<xsl:apply-templates/></xsl:with-param>
</xsl:call-template></xsl:if>
</xsl:template>
运行结果...<h2>The <I>Third</I> Major Section</h2>
<p>In addition to the inline tag in the heading, this section defines the term <i>inline</i>, which literally means "no line break". It also adds a simple link to the main page for the Java platform (<a href="http://java. sun.com">http://java.sun.com</a>), as well as a link to the <a href="http://java.sun.com/xml">XML</a> page.
</p>
XSLT 的其它功能 include, import for-each 生成编号 格式化编号 输出排序 基于模式的模板<apply-template mode=“…”>
用 Xalan 从命令行转换java org.apache.xalan.xslt.Process-IN article3.xml -XSL article3.xsl-OUT article3.html
用过滤器链连接转换File stylesheet1 = new File(argv[0]);File stylesheet2 = new File(argv[1]);File datafile = new File(argv[2]);BufferedInputStream bis = new BufferedInputStream(newFileInputStream(dataf
ile));InputSource input = new InputSource(bis);SAXParserFactory.newInstance(); spf.setNamespaceAware(true);SAXParser parser = spf.newSAXParser();XMLReader reader = parser.getXMLReader();SAXTransformerFactory stf = (SAXTransformerFactory) TransformerFactory.newI
nstance(); XMLFilter filter1 = stf.newXMLFilter( new StreamSource(stylesheet1)); XMLFilter filter2 = stf.newXMLFilter( new StreamSource(stylesheet2));filter1.setParent(reader);filter2.setParent(filter1);StreamResult result = new StreamResult(System.out); Transformer transformer = stf.newTransformer(); SAXSource transformSource = new SAXSource(filter2, input);transformer.transform(transformSource, result);
了解过滤器如何工作
测试程序<?xml version="1.0"?><Article>
<ArtHeader><Title>Title of my (Docbook) article</Title>
</ArtHeader><Sect1>
<Title>Title of Section 1.</Title><Para>This is a paragraph.</Para>
</Sect1></Article>
作为 filter1 的 xsl 文件<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform“ v
ersion="1.0“><xsl:output method="xml"/><xsl:template match="/">
<ARTICLE><xsl:apply-templates/>
</ARTICLE></xsl:template><xsl:template match="/Article/ArtHeader/Title">
<TITLE> <xsl:apply-templates/> </TITLE></xsl:template> <xsl:template match="//Sect1">
<SECT><xsl:apply-templates/></SECT></xsl:template> <xsl:template match="Para">
<PARA><xsl:apply-templates/></PARA></xsl:template>
</xsl:stylesheet>
过滤器链连接转换结果<html><body><h1 align="center">Title of my (Docbook) article</h1><h2>Title of Section 1.</h2><p>This is a paragraph.</p></body></html>
top related