XML/JSP婵犵數鍋為崹鍫曞蓟閵娾晩鏁勯柛鈩冾殢濞兼牠鏌ㄩ悤鍌涘
Hello,XML XML&Java/JSP濠电姵顔栭崰妤冩暜閹烘纾瑰ù鐘差儏闁卞洭鏌ㄩ悤鍌涘 JSP+XML闂傚倷鑳堕幊鎾绘倶閸儱纾婚柟鍓х帛閻撴盯鏌涢顐簻闁诲骏绲跨槐鎾诲醇閻斿妫嗛梺纭呭紦閸楁娊寮幘缁樻櫢闁跨噦鎷� JSP+XML闂傚倷绀侀幖顐︻敄閸涱垪鍋撳鐓庢珝闁诡喚鏁婚、娑樷攦閹傚闂侀潻瀵岄崢鍏肩閹烘梻纾奸悹浣筋潐鐎氾拷-Sparks.com Serving XML with JSP XML缂傚倸鍊搁崐椋庣矆娴g儤宕查柟鐗堟緲鐟欙箓鏌嶈閸撶喎顫忔繝姘<闁靛牆鎳忛悘鎾绘⒑閻戔晜顫夐柟鍑ゆ嫹 IBM闂傚倷鐒﹂惇褰掑礉瀹€鍕瀭闁哄嫬灏�/Java闂傚倷娴囧銊╂倿閿曞倹鍋$憸鏃堝春閵忋倖鏅搁柨鐕傛嫹 **闂傚倷娴囧銊╂倿閿曞倹鍋$憸鏃堝春閵忋倖鏅搁柨鐕傛嫹 缂傚倸鍊烽悞锕傘€冮幇鏉跨闁跨噦鎷�1-3缂傚倸鍊烽悞锕€螞閹达箑绠柨鐕傛嫹 **闂傚倷娴囧銊╂倿閿曞倹鍋$憸鏃堝春閵忋倖鏅搁柨鐕傛嫹 缂傚倸鍊烽悞锕傘€冮幇鏉跨闁跨噦鎷�4缂傚倸鍊烽悞锕€螞閹达箑绠柨鐕傛嫹 **闂傚倷娴囧銊╂倿閿曞倹鍋$憸鏃堝春閵忋倖鏅搁柨鐕傛嫹 缂傚倸鍊烽悞锕傘€冮幇鏉跨闁跨噦鎷�5缂傚倸鍊烽悞锕€螞閹达箑绠柨鐕傛嫹 **闂傚倷娴囧銊╂倿閿曞倹鍋$憸鏃堝春閵忋倖鏅搁柨鐕傛嫹 闂傚倸鍊搁崐鍝モ偓姘煎墰閳ь剚鍑归崜娑氭閻愮儤鏅搁柨鐕傛嫹1 濠电姷鏁告慨宥夊礋椤愩埄娼曢梻浣哥枃椤曆囧触鐎n喖绠氶柡鍐ㄧ墛閺呮悂鏌ㄩ悤鍌涘 **闂傚倷娴囧銊╂倿閿曞倹鍋$憸鏃堝春閵忋倖鏅搁柨鐕傛嫹 闂傚倸鍊搁崐鍝モ偓姘煎墰閳ь剚鍑归崜娑氭閻愮儤鏅搁柨鐕傛嫹2 濠电姷鏁告慨宥夊礋椤愩埄娼曢梻浣哥枃椤曆囧触鐎n喖绠氶柡鍐ㄧ墛閺呮悂鏌ㄩ悤鍌涘 闂備浇宕垫慨鎶芥⒔瀹ュ纾规繛鎴欏灪閸庡﹪鏌熸笟鍨刊L Server Java婵犵數鍋為崹鍫曞箰閹间焦鐒绘俊妤冾樋闂傚倷鐒﹂惇褰掑礉瀹€鈧埀顒佸嚬閸撶喖寮婚敃鍌氱厸闁告劏鏅涙禒鎺楁煟韫囨洖浠╅柛瀣姍閹兘顢涢悙瀵稿幗闂佹寧绻傜换鎴犫偓姘炬嫹 JDOM--XML闂傚倷鐒﹂惇褰掑礉瀹€鍕惞婵℃儳鍏檃闂傚倷鑳堕、濠囶敋瑜忛幑銏犖旈崨顓㈠敹闂佽法鍣﹂幏锟� Apache闂傚倷鐒﹂惇褰掑礉瀹€鍕瀭闁哄嫬灏庢繝纰夌磿閸嬫垿宕愰弴鐑囪€块柛妤冧紳濞差亝鏅搁柨鐕傛嫹 Cocoon闂傚倷鐒﹂惇褰掑礉瀹€鈧埀顒佸嚬閸撶喖骞冩ィ鍐ㄎ╃憸搴ㄥ疮閹达附鐓ラ柣鏇炲€圭€氾拷 XML DTD婵犵數鍋涢顓熸叏閹绢噮鏁勯柛銉㈡櫅閸ㄦ繈鏌ㄩ悤鍌涘 XML Schema闂傚倷鑳舵灙缂佽鐗撳畷鏇㈡濞磋櫕鐩弫鎾绘晸閿燂拷 JSP婵犵數鍋為崹鍫曞箰閹间焦鐒绘俊妤冾樋闂傚倷鐒﹂惇褰掑礉瀹€鈧埀顒佸嚬閸ㄨ京绮嬮幒妤€閱囬柕澶堝劤椤撳ジ姊虹捄銊ユ珢闁瑰嚖鎷� XML婵犵數鍋為崹鍫曞箰閸涘﹦鈻旀繛鎾茬畭a闂傚倷鐒﹂惇褰掑礉瀹€鈧埀顒佸嚬閸欏啫顕i幎鑺ュ亜闁绘挸娴烽澶婎渻閵堝棙鐓ュ褌绮欓獮蹇涘Ω閳哄倸鈧敻鏌h閹诧紕鈧熬鎷�
|
Java XML教程
来源:http://d23xapp2.cn.ibm.com/developerWorks/education/xml/xmljava/tutorial/xmljava-1-1.html
第四章 SAX- Simple API for XML
SAX 是解析 XML 文档的一个事件驱动(event-driven)的 API。在我们的 DOM 解析示例中,我们将 XML 文档发送给解析器,解析器处理整个文档,然后我们得到一个 Document 对象代表了我们的文档。
在 SAX 模型中,我们发送 XML 文档给解析器,解析器在发生一些时间时通知我们。由我们决定如何处理这些事件;如果我们忽略它们,在事件中的信息被丢弃。
示例代码
在我们继续以前,请下载我们的示例 XML 应用。解开 xmljava2.zip 文件,我们就可开始了!(记住您将文件放在何处。)
SAX 事件
SAX API 定义了一些事件。您可编写 Java 代码来处理您所关心的所有事件。如果您对某些类型的事件不关心,您不需要编写任何代码。只要忽略事件,解析器将会丢弃它。
一小列 SAX 事件
我们将在这里和下一页上列出大多数的 SAX 事件。在此页上的所有事件是常用的;在下一页的事件则比较偏了。它们都在 org.xml.sax 包的 HandlerBase 类中定义。
startDocument
表示文档开始。
endDocument
表示文档结束。
startElement
表示元素开始。当一对标记中的起始标记中的所有内容被处理后,解析器激发此事件。包括了标记名和其属性。
endElement
表示元素结束。
characters
包含字符数据,类似于 DOM 的一个 Text 节点。
更多的 SAX 事件
还有更多的 SAX 事件:
ignorableWhitespace
此事件类似于我们前面所讨论的无用 DOM 节点。它与 character 事件的区别好处是;如果您不需要空格符,您可以通过忽略这个事件来忽略所有的空格符。
warning、error 和 fatalError
这三个事件表示了解析错误。您可根据需要来响应它们。
setDocumentLocator
这个事件允许您存储一个 SAX 的 Locator 对象。Locator 对象可以用来找出在文档中确切发生事件的地方。
关于 SAX 接口
SAX API 实际上定义了四个接口来处理事件:EntityHandler、DTDHandler、DocumentHandler 和 ErrorHandler。所有这些接口都由 HandlerBase 来实现。
大多数情况下,您的 Java 代码将继承 HandlerBase 类。如果您想要划分代码的功能(也许您已经编写了非常好的 DTDHandler 类),您能分别实现 xxxHandler 类。
我们的首个 SAX 应用!
让我们运行我们的第一个 SAX 应用。这个应用类似于 domOne,但它使用的是 SAX API 而不是 DOM。
在命令行窗口,运行如下命令:
java saxOne sonnet.xml
这载入我们的应用并让它解析 sonnet.xml 文件。如果一切运行正常,您将在控制台看到 XML 文档的内容输出。
saxOne.java (代码请参见附录)
这是我们的第一个 SAX 应用。它解析一个 XML 文档并将其内容输出到标准输出。
<?xml version="1.0"?>
<sonnet type="Shakespearean">
<author>
<last-name>Shakespeare</last-name>
<first-name>William</first-name>
<nationality>British</nationality>
<year-of-birth>1564</year-of-birth>
<year-of-death>1616</year-of-death>
</author>
<title>Sonnet 130</title>
<lines>
<line>My mistress?eyes are ...
saxOne 概览
saxOne 的结构与 domOne 在多个方面有差别。首先,saxOne 继承了 HandlerBase 类。
其次,saxOne 有多个方法,每个对应于一个特定的 SAX 事件。由于每个类型的事件由每个方法来完全处理简化了我们的代码。
SAX 方法的签名(signature)
当您继承不同的 SAX 方法来处理 SAX 事件,您需要使用正确的方法签名。下面是大多数方法的签名:
startDocument() 和 endDocument()
这些方法没有参数。
startElement(String name, AttributeList attrs)
name 是刚开始的元素名,而 attrs 包含了该元素的所有属性。
endElement(String name)
name 是刚结束的元素名。
characters(char ch[], int start, int length)
ch 是否一个字符数组,start 是此事件中第一个字符在数组开始的位置,而 length 是在此事件中字符的数目。
public void startDocument()
...
public void startElement(String name,
AttributeList attrs)
...
public void characters(char ch[],
int start, int length)
...
public void ignorableWhitespace(char ch[],
int start int length)
...
public void endElement(String name)
...
public void warning(SAXParseException ex)
...
public void error(SAXParseException ex)
...
public void fatalError(SAXParseException
ex)
throws SAXException
...
处理命令行
如在 domOne 中一样,我们检查用户是否在命令行上有否输入。如果没有,我们打印使用方法并推出;否则,我们假定命令行上第一个参数( Java 语言中的 argv[0] ) 是文档名。我们忽略用户可能输入的其它参数。
public static void main(String argv[])
{
if (argv.length == 0)
{
System.out.println("Usage: ... ");
...
System.exit(1);
}
saxOne s1 = new saxOne();
s1.parseAndPrint(argv[0]);
}
创建一个 saxOne 对象
在我们的示例代码中,我们创建一个单独的 saxOne类。main 过程创建该类的一个实例并用它来解析我们的 XML 文档。由于 saxOne 继承 HandlerBase 类,我们可以使用 saxOne 作为一个 SAX 解析器的事件句柄。
public static void main(String argv[])
{
if (argv.length == 0)
{
System.out.println("Usage: ... ");
...
System.exit(1);
}
saxOne s1 = new saxOne();
s1.parseAndPrint(argv[0]);
}
创建一个 Parser 对象
现在我们已经要求我们的 saxOne 实例来解析和处理 XML 文档,它首先创建一个新的 Parser 对象。在这个示例中,我们使用 SAXParser 类而不再是 DOMParser 了。
注意我们在解析文档前,调用了两个方法 setDocumentHandler 和 setErrorHandler。这些方法通知我们新创建的 SAXParser 使用 saxOne 来处理事件。
SAXParser parser = new SAXParser();
parser.setDocumentHandler(this);
parser.setErrorHandler(this);
try
{
parser.parse(uri);
}
解析 XML 文档
一旦我们的 SAXParser 对象被建立,它只需要一行代码来处理我们的文档。如 domOne 中一样,我们将解析语句放置在一个 try 语句块中这样我们能捕获任何出现的错误。
SAXParser parser = new SAXParser();
parser.setDocumentHandler(this);
parser.setErrorHandler(this);
try
{
parser.parse(uri);
}
处理 SAX 事件
在 SAXParser 对象解析我们的文档的同时,当不同 SAX 事件出现时它调用我们对 SAX 事件句柄的实现。由于 saxOne 只是简单地将 XML 文档写回到控制台,每个事件句柄将对应的信息写到 System.out。
对 startElement 事件,我们输出原始标记的 XML 语法。对 character 事件,我们输出字符到屏幕上。对 ignorableWhitespace 事件,我们就将这些字符输出到屏幕上;这确保了原始文档的任何回车符和空格符也被输出。
public void startDocument()
...
public void startElement(String name,
AttributeList attrs)
...
public void characters(char ch[],
int start, int length)
...
public void
ignorableWhitespace(char ch[],
int start, int length)
...
一串可忽略的事件
如 DOM 一样,SAX 接口返回您所未预计的更多事件。我们在左边通过运行 java saxCounter sonnet.xml 命令生成了列表。
SAX 接口的一个好处是 25 个 ignorableWhitespace 事件只是简单地被忽略了。我们不需要编写代码来处理这些事件,而且我们不需要写代码来丢弃它们。
(saxCounter.java见附录)
这段代码解析一个 XML 文档并统计其接受到的 SAX 事件数据。当整个文档被解析完后,该代码将数据输出到标准输出。
Document Statistics for sonnet.xml:
====================================
DocumentHandler Events:
startDocument 1
endDocument 1
startElement 23
endElement 23
processingInstruction 0
character 20
ignorableWhitespace 25
ErrorHandler Events:
warning 0
error 0
fatalError 0
----------
Total: 93 Events
示例的事件列表
对下边的文档片断,下列是由解析器返回的事件:
一个 startDocument 事件
一个 startElement 事件对应 <sonnet> 元素
一个 ignorableWhitespace 事件对应回车符和在 <author> 标记前的两个空格符
一个 startElement 事件对应 <author> 元素
一个 ignorableWhitespace 事件对应回车符和在 <last-name> 标记前的四个空格符
一个 startElement 事件对应 <last-name> 标记
一个 character 事件对应 "Shakespeare" 这段字符
一个 endElement 事件对应 <last-name> 标记
<sonnet type="Shakespearean">
<author>
<last-name>Shakespeare</last-name>
SAX 对 DOM - 第一部分
为了介绍 SAX API,我们对原来的 domOne 程序重新用 SAX 编写。要了解这两者的区别,我们将讨论其解析过程。
对我们的第一个示例,要对所有包含 "Agamemnon," 的诗句解析出 The Iliad,SAX API 要高效的多。我们将查找 <verse> 的 startElement 事件,然后查看每个 character 事件。我们将保存来自任何包含 "Agamemnon," 事件的字符数据然后丢弃掉剩余的部分。
用 DOM 来实现则需要我们构建 Java 对象来表示文档的任意部分,将其保存在一棵 DOM 树中,然后在 DOM 树中查找包含我们所需文本的 <verse> 元素。这需要大量内存,而且解析器生成的大部分对象在被使用前都会被丢弃掉。
...
<book id="1">
<verse>
Sing, O goddess, the anger
of Achilles son of Peleus,
that brought countless ills
upon the Achaeans. Many
a hero did it yield a prey
to dogs and vultures, for so
were the counsels of Jove
fulfilled from the day on
which the son of Atreus,
king of men, and great
Achilles, first fell out
with one another.
</verse>
<verse>
...
SAX 对 DOM - 第二部分
反而言之,如果我们解析一个包含 10,000 条地址的 XML 文档,而我们需要按姓来将其排序,使用 SAX API 可能就很困难了。
我们需要构建一个数据结构来存放每个发生的 character 和 startElement 事件。一旦我们构建出所有这些元素,我们需要将其排序,然后编写一个方法按次序将其输出。
使用 DOM API 反而会节约时间。DOM 可以自动地对数据排序,而且我们可以使用 DOM 功能在 DOM 树中移动数据。
总结
到此为止,我们已经讨论了处理 XML 文档的两大主要 API。我们也讨论了您在何时使用哪个。
在我们的最后一章中,我们将讨论您在构建一个 XML 应用时可能使用的一些解析器的高级功能。
|