<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    即使世界明天毀滅,我也要在今天種下我的葡萄樹。
    posts - 112, comments - 14, trackbacks - 0, articles - 11

    用于XML的簡單API

    Posted on 2007-01-16 16:26 閱讀(430) 評論(0)  編輯  收藏 所屬分類: XML Design

    替換和插入文本

    下面要做的事情就是自定義解析器,你可以知道如何得到通常會忽略的信息。但是在這之前,先要學(xué)習(xí)一些重要的XML概念。本節(jié)中,要學(xué)習(xí):

    ·?? ??處理特殊字符("<", "&",等等)

    ·?? 使用XML風(fēng)格語法處理文本

    處理特殊字符

    XML中,實體是具有名字的XML結(jié)構(gòu)(或純文本)。通過名字引用實體將實體插入到文檔中實體引用的位置。創(chuàng)建實體引用時,使用“&”和分號將實體名包圍起來,如下所示:

    ??&entityName;

    后面學(xué)習(xí)如何編寫DTD時,你會發(fā)現(xiàn)可以自己定義實體,所以&yourEntityName; 可以變成你定義的實體的所有文本?,F(xiàn)在,主要討論預(yù)定義實體和不需要任何特殊定義的字符引用。

    預(yù)定義實體

    類似于&amp; 的實體引用包含一個名字,該名字在定界符之間 (本例中就是"amp")。它引用的文本(&)被用來替換名字,類似于C 或 C++程序中的宏。表 6-1 顯示了特殊字符的預(yù)定義實體。

    6-1 預(yù)定義實體

    字符

    引用

    &

    &amp;

    <

    &lt;

    >

    &gt;

    "

    &quot;

    '

    &apos;

    字符引用

    類似于&#147; 的字符引用包含散列符號(#),該符號后面跟著數(shù)字。數(shù)字是單個字符的Unicode值,如65代表字母"A",147代表左引號,148表示右引號。在本例中,實體的 "name"為散列符號,它后面跟著用來標(biāo)識字符的數(shù)字。

    注意:XML中最好用十進(jìn)制來表示值。然而 http://www.unicode.org/charts/ 的Unicode表用十六進(jìn)制表示值。所以需要進(jìn)行轉(zhuǎn)換,以便將正確的值插入XML數(shù)據(jù)集中。

    在XML文檔中使用實體引用

    假設(shè)你想要在你的XML文檔中插入下面一行內(nèi)容:

    ?Market Size < predicted

    直接在XML文件中添加該行的問題是,當(dāng)解析器看到左尖括號(<)時,它開始查找標(biāo)簽名,這就會脫離解析。為了解決該問題,在文件中用&lt;替代"<" 。

    注意:下面的修改結(jié)果包含在 slideSample03.xml中。它的處理結(jié)果在Echo07-03.txt.中。(可瀏覽版本是slideSample03-xml.htmlEcho07-03.html.)

    如果你按照該編程教程進(jìn)行學(xué)習(xí),在r slideSample.xml 文件中添加下面的文本:

    ??<!-- OVERVIEW -->
    ??<slide type="all">
    ????<title>Overview</title>
    ????...
    ??</slide>
    				??<slide type="exec">
    		
    				????<title>Financial Forecast</title>
    		
    				????<item>Market Size &lt; predicted</item>
    		
    				????<item>Anticipated Penetration</item>
    		
    				????<item>Expected Revenues</item>
    		
    				????<item>Profit Margin </item>
    		
    				??</slide>
    				
    				
    				
    				
    		
    </slideshow>

    在XML文件上運(yùn)行該Echo程序時,可以得到下列輸出結(jié)果:

    ELEMENT:????????<item>
    CHARS:????????Market Size < predicted
    END_ELM:????????</item>

    解析器將引用轉(zhuǎn)化為它表示的實體,并將該實體傳遞給應(yīng)用程序。

    使用XML-風(fēng)格的語法處理文本

    在處理包含多個特殊字符的XML或 HTML塊時,使用合適的實體引用替換每個特殊字符很不方便。在這種情況下,可以使用CDATA 段。


    注意:修改結(jié)果包含在slideSample04.xml中。處理結(jié)果在Echo07-04.txt中。(可瀏覽版本是 slideSample04-xml.htmlEcho07-04.html.)

    HTMLCDATA 段的功能類似于<pre>...</pre> ,只是—— CDATA 段中的所有空白都很重要,并且不將其中的字符解釋為XML。CDATA 段從<![CDATA[ 開始,并以]]>結(jié)束。將下面的文本添加到slideSample.xml 文件,為虛構(gòu)的技術(shù)幻燈片定義CDATA 段:

    ?? ...
    				??<slide type="tech">
    		
    				????<title>How it Works</title>
    		
    				????<item>First we fozzle the frobmorten</item>
    		
    				????<item>Then we framboze the staten</item>
    		
    				????<item>Finally, we frenzle the fuznaten</item>
    		
    				????<item><![CDATA[Diagram:
    		
    				??????frobmorten <--------------- fuznaten
    		
    				????????| ?? <3>??^
    		
    				????????| <1>????|??<1> = fozzle
    		
    				????????V ????|??<2> = framboze 
    		
    				????????Staten--------------------+??????<3> = frenzle
    		
    				?????????? <2>
    		
    				????]]></item>
    		
    				??</slide>
    		
    </slideshow>

    在新文件上運(yùn)行Echo 程序時,得到下列結(jié)果:

    ??ELEMENT: <item>
    ??CHARS:?? Diagram:
    ?
    frobmorten <--------------fuznaten
    ?????| ?????????<3>??????????^
    ???? | <1>? ????????????????|?? <1> = fozzle
    ????V? ????????????????|?? <2> = framboze 
    ??staten----------------------+?? <3> = frenzle
    ???????????<2>
    ?
    END_ELM: </item>

    可以看到一旦編寫了CDATA 段中的文本,就能夠得到它。由于解析器不將尖括號作為XML,所以它們不會產(chǎn)生致命錯誤 (因為,如果尖括號不在CDATA段中,文檔的結(jié)構(gòu)就不好)。

    處理CDATA 和其他字符

    CDATA的存在使得正確回送XML非常重要。如果要輸出的文本不在CDATA段中,那么必須使用適當(dāng)?shù)膶嶓w引用替代文本中的尖括號、&和其他特殊符號。(替代左尖括號和&最重要, 如果不誤導(dǎo)解析器,它就能正確解釋其他字符)

    但是如果輸出結(jié)果在CDATA 段中,那么不用替換,以產(chǎn)生類似于上例中的文本。在類似于Echo這樣的簡單程序中,這并不是一件重要的事情。但是許多XML-過濾應(yīng)用程序希望進(jìn)行跟蹤,確定文本是否出現(xiàn)在CDATA段中,這樣是為了正確處理特殊字符。

    另一處需要留意的地方就是屬性。屬性值的文本中也能包含尖括號和分號,也需要使用實體引用來替換它。(屬性文本不能在CDATA段中,所以,這里不會存在替換問題)

    本教程的后面部分,會介紹如何使用LexicalHandler 來判斷是否正在處理CDATA 段。然后,會介紹如何定義DTD。

    創(chuàng)建文檔類型定義 (DTD)

    在XML聲明之后,文檔序言中能引入DTD,通過DTD可以指定XML文檔中可以引入的標(biāo)簽。同時告訴驗證解析器哪些標(biāo)簽是有效的,以及在什么布局下是有效的。DTD告訴驗證解析器和非驗證解析器希望在哪里出現(xiàn)文本,解析器根據(jù)什么原則判斷空白是不可忽略的還是可以忽略的。

    基本DTD定義

    例如,在解析幻燈片放映時,你會看到在注釋和幻燈片元素之前和之后多次調(diào)用方法characters 。在這些情況下,空白由行結(jié)束符和標(biāo)簽周圍的縮進(jìn)構(gòu)成。目標(biāo)是使得XML文檔可讀——空白并不總是文檔內(nèi)容的一部分。在開始學(xué)習(xí)DTD定義之前,首先告訴解析器什么地方的空白可以忽略。


    注意:本節(jié)定義的DTD包含在 slideshow1a.dtd中。 (可瀏覽的版本是 slideshow1a-dtd.html.)

    創(chuàng)建文件slideshow.dtd。 輸入XML聲明和注釋標(biāo)識該文件,如下所示:

    <?xml version='1.0' encoding='utf-8'?>
    <!-- 
    ??DTD for a simple "slide show". 
    -->

    然后,添加下面的文本,指定slideshow 元素僅包含slide 元素:

    <!-- DTD for a simple "slide show". -->
    				<!ELEMENT slideshow (slide+)>
    				
    				
    				
    				
    		

    可以看到,DTD標(biāo)簽以<! 開始,接著是標(biāo)簽名 (ELEMENT)。標(biāo)簽名之后是要定義的元素的名字 (slideshow),括號內(nèi)是一個或多個項目,表明元素的有效內(nèi)容。這樣,符號說明slideshow 包含一個或多個slide 元素。

    若沒有+號,該定義則表明slideshow 僅包含單個slide 元素。表6-2列出了在元素定義中可以使用的符號。

    6-2 ?DTD 元素限定符

    限定符

    名字

    含義

    ?

    問號

    可選 (零個或一個)

    *

    星號

    個或多個

    +

    加號

    一或多個

    括號內(nèi)可以引入多個元素,使用逗號分隔,并且可以在每個元素上使用一個符號來表明可能會出現(xiàn)該元素的多少個實例。逗號分隔列表說明了哪些元素是有效的并說明了它們出現(xiàn)的順序。

    也可以嵌套括號以分組多個項目。例如,在定義image 元素后,可以通過((image, title)+)聲明在幻燈片中每個image 元素必須和title 元素配對使用。這里,在image/title 對上使用加號表明可以出現(xiàn)一個或多個(image,title )對。

    定義文本和嵌套元素

    現(xiàn)在,已經(jīng)告訴了解析器哪里不能出現(xiàn)文本,下面來看看如何告訴解析器哪里能夠出現(xiàn)文本。添加下面的文本,以定義slidetitle、itemlist 元素:

    <!ELEMENT slideshow (slide+)>
    				<!ELEMENT slide (title, item*)>
    		
    				<!ELEMENT title (#PCDATA)>
    		
    				<!ELEMENT item (#PCDATA | item)* >
    				
    				
    				
    				
    		

    添加的第一行說明幻燈片包含一個title ,它后面是零個或多個元素項。這里沒有新的內(nèi)容了。下一行說明標(biāo)題包含完整的解析字符數(shù)據(jù) (PCDATA)。在該領(lǐng)域中這叫做"文本",但是在XML中,這叫做“解析字符數(shù)據(jù)”。 (這就將它和CDATA 段區(qū)分開來了,CDATA可能包含不需要解析的字符數(shù)據(jù)。) PCDATA后面的"#"號表明下面跟著的是特殊字,而不是元素名。

    最后一行介紹了垂直條(|),它代表了or 條件。這樣,可能出現(xiàn)PCDATAitem 。結(jié)尾處的星號表明它們中的任何一個可以連續(xù)出現(xiàn)零次或多次。該規(guī)范是混合內(nèi)容模型,因為任意多個item 元素可以包含在文本中。定義這樣的模型時要先指定#PCDATA ,并使用垂直條分割一些可選項,最后以星號結(jié)束。

    DTD的局限性

    如果能夠指定item 可以包含文本或在項目列表后可以有文本就更好了。但是事實表明在DTD中很難得到這樣的規(guī)范。例如,可以使用下面的方法定義一個item

    <!ELEMENT item (#PCDATA | (#PCDATA, item+)) >

    這樣當(dāng)然很精確,但是一旦解析器看到了#PCDATA 和垂直條,它就要求剩下的定義遵守混合內(nèi)容模型。但是該規(guī)范沒有遵守該模型,所以得到錯誤:Illegal mixed content model for 'item'. Found &#x28; ..., 'item'使用了非法的混合內(nèi)容模型。找到&#x28; ..., 這里的十六進(jìn)制字符28表示結(jié)束該定義的尖括號。

    同樣,重復(fù)定義item 元素是沒有用的。運(yùn)行驗證解析器的時候,下面的規(guī)范:

    <!ELEMENT item (#PCDATA) >
    <!ELEMENT item (#PCDATA, item+) >

    會產(chǎn)生"duplicate definition"(“重復(fù)定義”)警告。實際上,第二個定義會被忽略。所以現(xiàn)在看來定義一個混合內(nèi)容模型 (它允許item 元素包含在文本中)是目前能用的最好方法。

    除了上面提到的混合內(nèi)容模型的局限性外,沒有其他方法來限制指定的PCDATA 可能出現(xiàn)的文本。它是不是僅能包含數(shù)字?它是不是必須是日期格式的,還是能夠是貨幣格式?在DTD上下文中沒有辦法說明。

    最后,注意DTD不是層次結(jié)構(gòu)的。title 元素定義的應(yīng)用等價于slide 標(biāo)題和item 標(biāo)題。當(dāng)擴(kuò)展DTD允許使用HTML-風(fēng)格的標(biāo)簽和純文本時,就有必要根據(jù)slide標(biāo)題限制item標(biāo)題的大小。但是這樣做的唯一方法是給它們一個不同的名字,如“item-title。 由于DTD缺少層次結(jié)構(gòu),最后一行要求在命名空間中引入“字符連接層次結(jié)構(gòu)”(或它的等價物) 。所有這些局限性都是開發(fā)模式規(guī)范標(biāo)準(zhǔn)的基本動機(jī)。

    DTD中的特殊元素值

    最好不要使用括號擴(kuò)起來的元素列表,元素定義可以使用一或兩個特殊值: ANYEMPTYANY 規(guī)范表示元素可能包含其他定義的元素或PCDATA。這類規(guī)范通常用在通用的XML文檔(如創(chuàng)建字處理器)根元素中。在這類文檔中原文的元素可以以任何順序出現(xiàn),所以使用ANY 是有意義的。

    EMPTY 規(guī)范表示元素不包含任何內(nèi)容。所以允許你使用<flag/>標(biāo)簽的e-mail消息在DTD中有一行跟下面類似的內(nèi)容:

    <!ELEMENT flag EMPTY>

    引用DTD

    這時,DTD定義跟XML文檔不在同一文檔中。這意味著必須在XML 文檔中引用它,這使得DTD文件成為XML文件完整的文檔類型定義(DTD)的外部子集。后面可以看到,也可以在文檔中引入DTD的一部分。這樣的定義構(gòu)成了DTD的本地子集。


    注意:本節(jié)中編寫的XML包括在slideSample05.xml中。(可瀏覽版本是slideSample05-xml.html)。

    將下面幾行內(nèi)容添加到slideSample.xml 文件中引用DTD文件:

    <!--? A SAMPLE set of slides? -->
    				<!DOCTYPE slideshow SYSTEM "slideshow.dtd">
    				
    				
    				
    				
    		
    <slideshow ?

    同樣,DTD 標(biāo)簽以"<!"開始,在本例中,標(biāo)簽名DOCTYPE說明該文檔是slideshow,意味著文檔包含slideshow 元素和它內(nèi)部的所有內(nèi)容:

    <slideshow>
    ...
    </slideshow>

    該標(biāo)簽將slideshow 元素定義成文檔的根元素。每個XML文檔必須有一個根元素。就在這里指定該元素。換句話說,該標(biāo)簽將文檔content 認(rèn)為是slideshow。

    DOCTYPE 標(biāo)簽出現(xiàn)在XML聲明之后根元素之前。SYSTEM 標(biāo)識符指定DTD文件的位置。由于它不以http:/ or file:/這類前綴開始,故路徑跟XML文檔的位置相關(guān)。是否還記得setDocumentLocator 方法?解析器使用該信息查找DTD 文件,這就跟應(yīng)用程序查找和XML文檔相關(guān)的文件一樣。也要使用PUBLIC 標(biāo)識符指定使用唯一名字的DTD 文件——但是解析器必須能夠處理它。

    DOCTYPE 規(guī)范必須在XML文檔內(nèi)包含DTD 定義。這樣的定義包含在方括號內(nèi),如下所示:

    <!DOCTYPE slideshow SYSTEM "slideshow1.dtd" [
    				??...local subset definitions here...
    		
    				]>
    				
    				
    				
    				
    		

    后面會充分利用該功能來定義一些文檔中能使用的實體。

    DTD對非驗證解析器的影響

    在前一節(jié),定義了基本文檔類型,并在XML文件中使用了它。在本節(jié)中,將使用Echo程序說明引入DTD后,數(shù)據(jù)是如何出現(xiàn)在SAX解析器中的。


    注意:本節(jié)中的輸出結(jié)果在Echo07-05.txt中。(可瀏覽版本是Echo07-05.html)


    slideSample.xml 的最新版本上運(yùn)行Echo程序,可以看到許多對characters 方法的多余的調(diào)用消失了。

    以前是:

    ??...
    >
    PROCESS: ...
    				CHARS:
    		
    ??ELEMENT:????????<slide
    ????ATTR: ...
    ??>
    ??????ELEMENT:????????<title>
    ??????CHARS:????????Wake up to ...
    ??????END_ELM:????????</title>
    ??END_ELM:????????</slide>
    				CHARS:
    		
    ??ELEMENT:????????<slide
    ????ATTR: ...
    ??>
    ??...

    現(xiàn)在是:

    ??...
    >
    PROCESS: ...
    ??ELEMENT:????????<slide
    ????ATTR: ...
    ??>
    ??????ELEMENT:????????<title>
    ??????CHARS:????????Wake up to ...
    ??????END_ELM:????????</title>
    ??END_ELM:????????</slide>
    ??ELEMENT:????????<slide
    ????ATTR: ...
    ??>
    ??...

    很明顯,可以看到,解析器不再傳送以前回送到slide 元素旁邊的空白字符,這是因為DTD聲明, slideshow 僅僅包含slide 元素:

    ? <!ELEMENT slideshow (slide+)>

    跟蹤可忽略空白

    既然使用了DTD,解析器不再調(diào)用帶有無關(guān)空白的characters 方法。從僅對處理XML數(shù)據(jù)感興趣的應(yīng)用程序的觀點來看,這樣做非常好。應(yīng)用程序不再受到那些僅為增加XML文件可讀性的空白的干擾。

    另外,如果你正在編寫過濾XML數(shù)據(jù)文件的應(yīng)用程序,并且你希望該版本的文件具有相同的可讀性,那么這些空白就不會是無關(guān)的——它是必需的。要得到這些字符,必須在應(yīng)用程序中添加方法ignorableWhitespace 。下面你就要這樣做。


    注意:本節(jié)中編寫的代碼包含在Echo08.java中。輸出結(jié)果在Echo08-05.txt.中。(可瀏覽版本是Echo08-05.html)


    要處理解析器看到的可忽略的空白,添加下面的代碼,實現(xiàn)你自己的Echo程序中的ignorableWhitespace 事件處理程序:

    public void characters (char buf[], int offset, int len)
    ... 
    }
    				public void ignorableWhitespace char buf[], int offset, int Len)
    		
    				throws SAXException
    		
    				{
    		
    				??nl(); 
    		
    				??emit("IGNORABLE");
    		
    				}
    				
    				
    				
    				
    		
    public void processingInstruction(String target, String data)
    ...

    該代碼僅僅產(chǎn)生告訴你查看到了可忽略空白的消息。


    注意:同樣,不是創(chuàng)建的所有解析器都是相同的。SAX規(guī)范不要求調(diào)用該方法。只要DTD使得它可能,Java XML實現(xiàn)就這樣做。

    現(xiàn)在運(yùn)行Echo應(yīng)用程序,輸出結(jié)果如下所示:

    ELEMENT: <slideshow
    ??ATTR: ...
    >
    				IGNORABLE
    		
    				IGNORABLE
    		
    PROCESS: ...
    				IGNORABLE
    		
    				IGNORABLE
    		
    ??ELEMENT: <slide
    ????ATTR: ...
    ??>
    ??IGNORABLE
    ????ELEMENT: <title>
    ????CHARS:?? Wake up to ...
    ????END_ELM: </title>
    ??IGNORABLE
    ??END_ELM: </slide>
    				IGNORABLE
    		
    				IGNORABLE
    		
    ??ELEMENT: <slide
    ????ATTR: ...
    ??>
    ??...

    這里很明顯,在注釋和幻燈片元素之前和之后調(diào)用了可忽略空白,其中這之前調(diào)用的字符是DTD。

    清除

    既然已經(jīng)回送了可忽略空白,從你的Echo程序中刪除該代碼——前面的練習(xí)中已經(jīng)不再需要它們了。


    注意:該變化保存在Echo09.java中。

    文檔和數(shù)據(jù)

    前面,已經(jīng)介紹了同時存在XML documents和XML data這兩種叫法的原因之一在于,XML不管結(jié)構(gòu)中的元素之間是否允許使用文本,都能能否很好地處理它們。

    在使用的示例文件中,slideshow 元素是數(shù)據(jù)元素(data element)的一個例子——它僅包含子元素,且沒有插入文本。另外,item 元素可能會變成文檔元素(document element),因為它能引入了文本和子元素。

    在閱讀該教程的過程中,你會知道如何擴(kuò)展標(biāo)題元素的定義,讓它能引入HTML-風(fēng)格的標(biāo)記,這也會變成文檔元素。

    修改空元素

    現(xiàn)在你已經(jīng)理解了如何忽略空白的特定實例,可以修改“空”元素的定義了?,F(xiàn)在可以擴(kuò)展該元素以包含

    ? <foo>?? </foo>

    其中標(biāo)簽間有空白并且DTD定義的空白可忽略。

    定義DTD中的屬性和實體

    目前定義的DTD用于非驗證解析器。它說明了文本應(yīng)該出現(xiàn)在哪里不應(yīng)該出現(xiàn)在哪里,這些都是解析器所關(guān)心的。但是在驗證解析器的使用中,DTD需要指定不同元素的有效屬性。我們將在本節(jié)中實現(xiàn)它,然后再定義一個可以在XML文件中引用的內(nèi)部實體和外部實體。

    定義DTD中的屬性

    首先在幻燈片放映中定義元素屬性。


    注意:本節(jié)中編寫的XML包含在slideshow1b.dtd中。 (可瀏覽版本是:slideshow1b-dtd.html)

    添加下面的文本,定義slideshow 元素的屬性:

    <!ELEMENT slideshow (slide+)>
    				<!ATTLIST slideshow 
    		
    				????title??? CDATA??? #REQUIRED
    		
    				????date???? CDATA??? #IMPLIED
    		
    				????author?? CDATA??? "unknown"
    		
    				>
    		
    <!ELEMENT slide (title, item*)>

    DTD標(biāo)簽ATTLIST揭開了屬性定義的序幕。ATTLIST 后面的名字指定了要定義屬性的元素。這里,元素是slideshow 元素。(注意DTD規(guī)范中同樣缺少層次結(jié)構(gòu)) 。

    每個屬性由被三個空格隔開的值指定。不允許使用逗號和其他分隔符,所以如上所述的格式化定義對增強(qiáng)可讀性很有效。每行中的第一個元素是屬性的名字,這里是:title, dateauthor。 第二個元素表示了數(shù)據(jù)的類型:CDATA 是字符數(shù)據(jù)——不可解析數(shù)據(jù)。左尖括號(<)同樣是XML標(biāo)簽的一部分。表 6-3 提供了屬性類型的有效選擇。

    6-3 屬性類型

    屬性類型

    指定了 ...

    (value1 | value2 | ...)

    由垂直條分隔的值的列表 (例子在下面)

    CDATA

    "未解析的字符數(shù)據(jù)"。(對于一般人而言,這是文本字符串)

    ID

    不與其他ID屬性共享的名字

    IDREF

    對文檔其他地方定義的ID的引用

    IDREFS

    包含一個或多個ID引用的空格分隔的列表

    ENTITY

    DTD中定義的實體的名字

    ENTITIES

    空格間隔的實體的列表

    NMTOKEN

    有效的XML名字,由字母、數(shù)字、連字符、下劃線和冒號構(gòu)成

    NMTOKENS

    用空格間隔的名字列表

    NOTATION

    DTD指定的符號名,描述了非XML數(shù)據(jù)格式,比如圖像文件中使用的*

    *這是一個很快就過時的規(guī)范,在本節(jié)結(jié)尾處會詳細(xì)介紹。

    當(dāng)屬性類型包含括號括起來的由垂直條分隔的選項列表時,屬性必須使用指定值。例如,將下面的文本添加到DTD中:

    <!ELEMENT slide (title, item*)>
    				<!ATTLIST slide 
    		
    				????type?? (tech | exec | all) #IMPLIED
    		
    				>
    		
    <!ELEMENT title (#PCDATA)>
    <!ELEMENT item (#PCDATA | item)* >

    該規(guī)范說明slide 元素的type 屬性必須按如下方式給出:type="tech"type="exec", or type="all"。其他值不能接受。(能理解DTD的XML編輯器可以使用這樣的規(guī)范來表現(xiàn)選項的彈出列表。)

    屬性規(guī)范中的最后一項確定了屬性的默認(rèn)值,并說明了是否需要屬性。表6-4 列出了可用選項。

    6-4 屬性 - 規(guī)范參數(shù)

    規(guī)范

    指定 ...

    #REQUIRED

    文檔中必須指定屬性值

    #IMPLIED

    文檔中不需要指定屬性值。如果沒有指定,它會使用應(yīng)用程序提供的默認(rèn)值

    "defaultValue"

    如果文檔中沒有指定值,這就是要使用的默認(rèn)值

    #FIXED "fixedValue"

    要使用的值。如果文檔指定了所有值,它們必須相同

    定義DTD中的實體

    目前,已經(jīng)看到了類似于&amp; 這樣的預(yù)定義實體,并且看到實體中可以引用屬性?,F(xiàn)在可以開始學(xué)習(xí)如何定義實體。


    注意:這里定義的XML包含在slideSample06.xml中。輸出結(jié)果在Echo09-06.txt中。 (可瀏覽版本是slideSample06-xml.htmlEcho09-06.html.)


    將下面的文本添加到你的XML文件的DOCTYPE 標(biāo)簽中:

    <!DOCTYPE slideshow SYSTEM "slideshow.dtd" [
    				??<!ENTITY product? "WonderWidget">
    		
    				??<!ENTITY products "WonderWidgets">
    		
    				]>

    ENTITY 標(biāo)簽名說明正在定義一個實體。下面是實體名和它的定義。這里,定義了一個叫做“product”的實體,使用它來替代產(chǎn)品名。以后,一旦改變了產(chǎn)品名(通常會這樣),只需要改變一個地方的名字,然后,所有的幻燈片就都能夠使用該新值。

    最后一部分是XML文檔中實體引用時可以取代實體名的替換字符串。使用引號定義替代字符串,當(dāng)將文本插入文檔時沒有引入它們。

    為方便起見,我們定義了兩個版本,一個是單數(shù)一個是復(fù)數(shù)。當(dāng)市場專家遇到產(chǎn)品名"Wally"時,你將要輸入復(fù)數(shù)"Wallies"并且正確替換它。


    注意:老實說,這屬于外部DTD的范疇。這樣,當(dāng)名字改變時,所有的文檔能夠引用新的名字。但是,這是一個例子...


    既然已經(jīng)定義了實體,下面要在幻燈片放映中引用它們。進(jìn)行下面的修改實現(xiàn)該功能:

    <slideshow 
    ??title="WonderWidget&product; Slide Show" 
    ??...
    ??<!-- TITLE SLIDE -->
    ??<slide type="all">
    ????<title>Wake up to WonderWidgets&products;!</title>
    ??</slide>
    ?? <!-- OVERVIEW -->
    ??<slide type="all">
    ????<title>Overview</title>
    ????<item>Why <em>WonderWidgets&products;</em> are 
    great</item>
    ????<item/>
    ????<item>Who <em>buys</em> WonderWidgets&products;</item>
    ??</slide>

    這里要注意的是,你定義的實體被引用時用到的語法和用于預(yù)定義實體的相同(&entityName;),并且可以在屬性值和元素的內(nèi)容中引用實體。

    回送實體引用

    下面是在該版本的文件上運(yùn)行Echo 程序時看到的內(nèi)容:

    ELEMENT:????????<title>
    CHARS:????????Wake up to WonderWidgets!
    END_ELM:????????</title>

    注意,已經(jīng)使用了產(chǎn)品名替換了實體引用。

    其他有用實體

    下面是編寫XML文檔中可能有用的其他幾個實體定義的例子:

    <!ENTITY ldquo? "&#147;"> <!-- Left Double Quote --> 
    <!ENTITY rdquo? "&#148;"> <!-- Right Double Quote -->
    <!ENTITY trade? "&#153;"> <!-- Trademark Symbol (TM) -->
    <!ENTITY rtrade "&#174;"> <!-- Registered Trademark (R) -->
    <!ENTITY copyr? "&#169;"> <!-- Copyright Symbol --> ?

    引用外部實體

    也可以使用SYSTEMPUBLIC 標(biāo)識符命名在外部文件中定義的實體。現(xiàn)在就可以這樣做。


    注意:這里定義的XML包含在 slideSample07.xmlcopyright.xml中。輸出結(jié)果在Echo09-07.txt中。(可瀏覽版本是slideSample07-xml.html, copyright-xml.html Echo09-07.html.)


    為了引用外部實體,將下面的文本添加到XML文件的DOCTYPE 語句中:

    <!DOCTYPE slideshow SYSTEM "slideshow.dtd" [
    ??<!ENTITY product? "WonderWidget">
    ??<!ENTITY products "WonderWidgets">
    ??<!ENTITY copyright SYSTEM "copyright.xml">
    ]>

    該定義引用了一個包含在文件copyright.xml 中的版本信息。創(chuàng)建該文件并輸入一些有趣的文本,如下所示:

    ? <!--? A SAMPLE copyright? -->
    This is the standard copyright message that our lawyers
    make us put everywhere so we don't have to shell out a
    million bucks every time someone spills hot coffee in their
    lap...

    最后,將下面的文本添加到slideSample.xml 文件中,以引用外部實體:

    <!-- TITLE SLIDE -->
    ??...
    </slide>
    				<!-- COPYRIGHT SLIDE -->
    		
    				<slide type="all">
    		
    				??<item>&copyright;</item>
    		
    				</slide>
    				
    				
    				
    				
    		

    也可以使用外部實體聲明來訪問servlet,該servlet使用類似于下面的定義來產(chǎn)生當(dāng)前日期:

    <!ENTITY currentDate SYSTEM
    ??"http://www.example.com/servlet/CurrentDate?fmt=dd-MMM-
    yyyy"> ?

    可以使用跟引用其他實體相同的方法引用該實體:

    ? Today's date is &currentDate;.

    回送外部實體

    下面是在幻燈片放映的最新版本上運(yùn)行Echo程序時看到的內(nèi)容:

    ...
    END_ELM: </slide>
    ELEMENT: <slide
    ??ATTR: type????????"all"
    >
    ??ELEMENT: <item>
    ??CHARS: 
    This is the standard copyright message that our lawyers
    make us put everywhere so we don't have to shell out a
    million bucks every time someone spills hot coffee in their
    lap...
    ??END_ELM: </item>
    END_ELM: </slide>
    ...

    注意,文件中注釋后面的新行將作為字符回送,但是忽略注釋本身。這就是為什么版本消息出現(xiàn)在CHARS: 標(biāo)簽后面的下一行中,而不是直接在標(biāo)簽后面——實際上第一個回送的字符是注釋后面的新行。

    總結(jié)實體

    文檔內(nèi)容中引用的實體,不論是外部的還是內(nèi)部的都一概叫做一般實體。包含DTD內(nèi)引用的DTD規(guī)范的實體叫做參數(shù)實體(后面將會詳細(xì)介紹)。

    一個包含XML(文本和標(biāo)記)并且被解析的實體叫做已析實體(parsed entity)。一個包含二進(jìn)制數(shù)據(jù)的實體 (如圖像)叫做未析實體(unparsed entity)。(本質(zhì)來講,它必須是外部的)該教程的下一節(jié)主要討論對未析實體的引用。

    引用二進(jìn)制實體

    本節(jié)沒有編程練習(xí)。主要討論引用類似于圖像文件和多媒體數(shù)據(jù)文件這樣的二進(jìn)制時的選項。

    使用MIME數(shù)據(jù)類型

    有兩種方法可以引用類似于二進(jìn)制圖形文件的這類未析實體。一種方法是使用DTD的NOTATION-規(guī)范機(jī)制。然而,該機(jī)制是一個復(fù)雜的非直觀機(jī)制,通常用于兼容SGML文檔。在介紹DTDHandler API時會進(jìn)一步詳細(xì)地介紹它,但是現(xiàn)在已可以說結(jié)合最近定義的XML命名空間標(biāo)準(zhǔn),以及為電子郵件附件定義的MIME數(shù)據(jù)類型,為引用未析外部實體提供了一個更加有用、更易理解、更易擴(kuò)展的機(jī)制。


    注意:這里描述的XML在 slideshow1b.dtd中。我們實際上沒有回送任何圖像。這超過了本教程的Echo程序的范圍。本節(jié)僅用來理解如何進(jìn)行這類引用。它假設(shè)將要處理XML數(shù)據(jù)的應(yīng)用程序知道如何處理這類引用。


    將下面的文本添加到slideshow.dtd文件中,以便讓幻燈片顯示使用圖像文件:

    <!ELEMENT slide (image?, title, item*)>
    <!ATTLIST slide 
    ????type?? (tech | exec | all) #IMPLIED
    >
    <!ELEMENT title (#PCDATA)>
    <!ELEMENT item (#PCDATA | item)* >
    				<!ELEMENT image EMPTY>
    		
    				<!ATTLIST image 
    		
    				????alt??? CDATA??? #IMPLIED
    		
    				????src??? CDATA??? #REQUIRED
    		
    				????type?? CDATA??? "image/gif"
    		
    				>
    				
    				
    				
    				
    		

    這些改動聲明imageslide中的可選元素,將它定義為空元素,并定義它需要的屬性。該image 標(biāo)簽在HTML 4.0 標(biāo)簽img之后,添加了圖像類型標(biāo)識符type。(img 標(biāo)簽是在HTML 4.0規(guī)范中定義的)

    image 標(biāo)簽的屬性是由ATTLIST 項定義的。alt 屬性定義了在找不到圖像的情況下顯示的替代文本,它接受字符數(shù)據(jù)(CDATA)。這是一個“隱含”(implied)值,這表明它不是可選的,并且處理數(shù)據(jù)的程序知道如何替代像“圖像沒有找到”這樣的消息。另外,需要src 屬性來指定要顯示的圖像。

    在MIME數(shù)據(jù)類型中需要type 屬性,它定義在ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/.。它的默認(rèn)值為 image/gif。


    注意:這里可以知道類型屬性使用的字符數(shù)據(jù)(CDATA)是MIME數(shù)據(jù)類型中的一種。最常見的格式為: image/gifimage/jpeg。這樣,最好在這里指定屬性列表,使用下面的格式:

    type ("image/gif", "image/jpeg")

    然而,這沒有用,因為屬性列表受限于名字記號(name token)。正斜杠不是名字記號字符的有效部分,所以該聲明出錯。而且,在DTD中創(chuàng)建屬性列表將會將有效的MIME類型限制于這些定義中。仍然保持CDATA 使得它更加開放,所以定義了其他類型之后,該聲明仍然有效。


    文檔中,對"intro-pic"圖像的引用具有以下格式:

    <image src="image/intro-pic.gif", alt="Intro Pic", 
    type="image/gif" />

    另一選擇:使用實體引用

    使用MIME數(shù)據(jù)類型作為元素的屬性是一個非常靈活并可擴(kuò)展的機(jī)制。要使用符號機(jī)制創(chuàng)建外部ENTITY 引用,對于jpeg和gif數(shù)據(jù)需要DTD NOTATION 元素。當(dāng)然這些都可以從一些中央知識庫中取得。但是這樣你必須要為你想要引用的每個圖像定義不同的ENTITY 元素。換句話說,在文檔中添加新的圖像需要在DTD中進(jìn)行新實體定義也要在文檔中引用它。給定了普遍存在的HTML 4.0規(guī)范,更新的標(biāo)準(zhǔn)要使用MIME數(shù)據(jù)類型和聲明,如image ,它假設(shè)應(yīng)用程序知道如何處理這類元素。

    選擇解析器實現(xiàn)

    如果沒有指定其他factory類,就使用默認(rèn)的SAXParserFactory 類。使用不同制造商的解析器,可以改變指向它的環(huán)境變量的值??梢栽诿钚兄羞M(jìn)行該操作,如下所示:

    java -Djavax.xml.parsers.SAXParserFactory=yourFactoryHere ...

    你指定的factory名必須是完全合格的類名(包括所有的包前綴)。如果想獲得更多信息,請查看SAXParserFactory 類中的newInstance()方法的文檔。

    主站蜘蛛池模板: 亚洲av无码一区二区三区天堂古代| 日韩免费观看的一级毛片| a级毛片高清免费视频就| 亚洲精品视频免费观看| 特级毛片aaaa免费观看| 一级日本高清视频免费观看 | 国产亚洲色婷婷久久99精品91| 一区国严二区亚洲三区| 亚洲A∨午夜成人片精品网站| 四虎免费久久影院| 亚洲国产精品综合久久网络| 亚洲国产成人a精品不卡在线| 亚洲人AV永久一区二区三区久久| 亚洲精品视频免费| 亚洲国产香蕉人人爽成AV片久久| 亚洲麻豆精品国偷自产在线91| 亚洲无人区一区二区三区| 亚洲av永久无码精品表情包| 亚洲高清在线观看| 亚洲天堂一区在线| 亚洲私人无码综合久久网| 视频一区在线免费观看| 成在线人免费无码高潮喷水| 久久黄色免费网站| 97在线观免费视频观看| 精品少妇人妻AV免费久久洗澡| 可以免费观看的一级毛片| 精品亚洲视频在线观看| 亚洲精品免费在线观看| 精品亚洲456在线播放| 美女羞羞喷液视频免费| 中文成人久久久久影院免费观看 | 亚洲精品无码国产片| 色视频在线观看免费| 国内精品一级毛片免费看| 亚洲一区在线免费观看| 国产国产成年年人免费看片| 自拍偷自拍亚洲精品被多人伦好爽 | 一级毛片免费观看不卡视频| www.999精品视频观看免费| 免费日本黄色网址|