まえがき
むかしむかし、「ドキュメントオブジェクトモデル」という問題に遭遇しました。 XML自体のシンプルさと直感性にもかかわらず、提案されているパーサーAPIのほとんどは、XMLを扱うことの特性を掘り下げ始めたばかりの人にとってはやや面倒で理解しにくいものです。 はい、私は議論しません、これらはすべての可能な側面をカバーする複雑なソリューションですが、これは簡単ではありません
言うまでもなく、パーサーの開発者が誰も「日常使用」のための簡単なソリューションを提供しない(またはほとんどなし)のは、まだ謎のままです。 冒とくに接しているが、本質はこれから変わらない場合でも-問題とイデオロギー全体を掘り下げると、多くの時間を犠牲にしながら、大きく強力なツールを使用する能力が得られます。 おそらく、このツールの簡易バージョンが存在することで、本質をはるかに速く理解できるようになるでしょう。
しかし、今のところ、私は自分のために車輪を再発明しなければなりません。
今日、私はあなたのために自転車を転がしたいと思っています-Android向けXMLを扱うための少人数クラス 少なくともオリエンテーションのコースとして、多くの人に役立つと確信しています。
クラスのソースは非常にシンプルであり、その2つの最大の機能はそれぞれ40行をほとんど占有せず、行の総数は250未満です。 このテキストの最後にコピーできます。
説明
前述したように、このクラスはXML形式のデータを処理するように設計されています。 言うまでもなく、XMLを文字列またはストリームとして解析および形成でき、ノードのコンテンツおよび属性へのアクセスを提供しますが、ネームスペースでは機能しません。 おそらく後者は欠点かもしれませんが、名前空間を操作する必要性を自分で満たしていないため、ノードの十分な属性とコンテンツがあります。
例を考えてみましょう:
SimpleXML xml = new SimpleXML ( "Home" ) ;
SimpleXML子= xml。 createChild ( "Child" ) ;
子 setAttr ( "name" 、 "Vasya" ) ;
子 setAttr ( "sex" 、 "male" ) ;
子 setAttr ( "age" 、 "5" ) ;
SimpleXML dog = xml。 getNodeByPath ( "Pets \\ Dog" 、 true ) ;
犬。 setAttr ( "name" 、 "Druzshok" ) ;
犬。 setAttr ( "age" 、 "3" ) ;
文字列 xmlOut = SimpleXML。 saveXml ( xml ) ;
この例を使用して、次の内容の文字列を作成しました。
<?xml version = '1.0' encoding = 'Utf-8' standalone = 'yes' ?>
<ホーム>
<Child sex = "male" age = "5" name = "Vasya" > </ Child >
<ペット>
<Dog age = "3" name = "Druzshok" > </ Dog >
</ペット>
</ホーム>
結果のコンテンツをオブジェクトにロードします。
SimpleXML xml2 = SimpleXML。 loadXml ( xmlOut ) ;
if ( xml2 != null ) {
//持っているノードの数を調べる
int nodeCount = xml2。 getChildCount ( ) ;
ベクター< SimpleXML > children = xml2。 getChildren ( "Child" ) ;
if ( children != null && children。size ( ) > 0 ) {
for ( SimpleXML子:子) {
//子ノードのセットでアクションを実行します
}
}
SimpleXML dog = xml2。 getNodeByPath ( "Pets \\ Dog" 、 false ) ;
if ( dog != null ) {
//犬が見つかりました。 彼女に電話する方法を学ぶ。
文字列 dogName = dog。 getAttr ( "name" ) ;
if ( ! dogName。equals ( "" ) ) {
// dog dogNameを呼び出すことを学びました
}
//犬が持っている属性の数を見てみましょう
int dogAttrCount = dog。 getAttrCount ( ) ;
//おばあちゃんに犬をあげる
SimpleXML xmlGrandma = new SimpleXML ( "Grandma" ) ;
//おばあちゃんに動物がいなくても、おばあちゃんは動物であることがわかります
SimpleXML xmlGrandmaPets = xmlGrandma。 getNodeByPath ( "Pets" 、 true ) ;
犬。 setParent ( xmlGrandmaPets ) ;
//そして、もし彼がそうなら、我々は祖母から猫を連れて行きます
SimpleXML cat = xmlGrandma。 getNodeByPath ( "Pets \\ Cat" 、 false ) ;
if ( cat != null ) {
猫。 setParent ( xml2 ) ;
}
}
子供たちのリストを入手し、犬を見つけ、そのニックネームを学び、この犬をおばあちゃんに渡すことができましたが、猫の存在は疑わしいです。 そしてこれは素晴らしい!
そして今、クラス自体:
import java.io.ByteArrayInputStream ;
import java.io.ByteArrayOutputStream ;
import java.io.InputStream ;
import java.util.HashMap ;
import java.util.Iterator ;
import java.util.Vector ;
import java.util.Map.Entry ;
import javax.xml.parsers.DocumentBuilder ;
import javax.xml.parsers.DocumentBuilderFactory ;
import org.w3c.dom.Document ;
import org.w3c.dom.NamedNodeMap ;
import org.w3c.dom.Node ;
import org.w3c.dom.NodeList ;
import org.xmlpull.v1.XmlSerializer ;
import android.util.Log ;
import android.util.Xml ;
パブリック クラス SimpleXML {
プライベート SimpleXML fparent ;
プライベート 文字列 ftext ;
プライベート 文字列 fname ;
private Vector < SimpleXML > fchild ;
private HashMap < String、String > fattrs ;
public String getText ( ) {
ftextを返します。
}
public void setText ( String newText ) {
ftext = newText ;
}
public String getAttr ( String attrName ) {
if ( fattrs。containsKey ( attrName ) ) fattrsを返します。 get ( attrName ) ;
return "" ;
}
public void setAttr ( String attrName、 String attrValue ) {
fattrs。 put ( attrName、attrValue ) ;
}
public int getAttrCount ( ) {
fattrsを返します。 サイズ ( ) ;
}
public int getChildCount ( ) {
子を返します。 サイズ ( ) ;
}
public Vector < SimpleXML > getChildren ( ) {
子を返す ;
}
public SimpleXML getParent ( ) {
親を返す;
}
public void setParent ( SimpleXML newParent ) {
if ( fparent != null ) {
{
ペアレント。 子 。 削除 ( これ ) ;
} catch ( 例外 e ) { }
}
if ( newParent instanceof SimpleXML ) {
fparent = newParent ;
{
ペアレント。 子 。 追加 ( これ ) ;
} catch ( 例外 e ) { }
} else {
fparent = null ;
}
}
public SimpleXML ( String nodeName ) {
fname = nodeName ;
ftext = "" ;
fattrs = new HashMap < String、String > ( ) ;
fchild = new Vector < SimpleXML > ( ) ;
fparent = null ;
}
public static SimpleXML fromNode ( Node node ) {
SimpleXML ret = null ;
if ( node != null ) {
{
ret = new SimpleXML ( node。getNodeName ( ) ) ;
if ( node。hasAttributes ( ) ) {
NamedNodeMap nattr = node。 getAttributes ( ) ;
for ( int f = 0 ; f < nattr。getLength ( ) ; ++ f ) {
ret。 setAttr ( nattr.item ( f ) .getNodeName ( ) 、nattr.item ( f ) .getNodeValue ( ) ) ;
}
}
if ( node。hasChildNodes ( ) ) {
NodeList nlc =ノード。 getChildNodes ( ) ;
for ( int f = 0 ; f < nlc。getLength ( ) ; ++ f ) {
if ( nlc。item ( f ) 。getNodeType ( ) == Node。TEXT_NODE ) {
ret。 ftext + = nlc。 アイテム ( f ) 。 getNodeValue ( ) ;
} else if ( nlc。item ( f ) 。getNodeType ( ) == Node。ENTITY_REFERENCE_NODE ) {
文字列 nv = nlc。 アイテム ( f ) 。 getNodeName ( ) ;
if ( nv != null && nv。length ( ) > 1 && nv。startsWith ( "#" ) )) {
nv = nv。 部分文字列 ( 1 ) ;
{
int [ ] z = { 整数 。 parseInt ( nv ) } ;
String s = new String ( z、 0 、 z。Length ) ;
ret。 ftext + = s ;
} catch ( 例外 e ) { }
}
} else {
SimpleXML rchild = SimpleXML。 fromNode ( nlc。item ( f ) ) ;
if ( rchild != null ) ret。 getChildren ( ) 。 add ( rchild ) ;
}
}
}
} catch ( 例外 e ) { }
}
return ret ;
}
public SimpleXML createChild ( String nodeName ) {
SimpleXML child = new SimpleXML ( nodeName ) ;
子 setParent ( これ ) ;
子を返す ;
}
public Vector < SimpleXML > getChildren ( String nodeName ) {
Vector < SimpleXML > ret = new Vector < SimpleXML > ( ) ;
{
イテレータ< SimpleXML > i = fchild。 イテレータ ( ) ;
while ( i。hasNext ( ) ) {
SimpleXML xml = i。 次へ ( ) ;
if ( xml。fname。equalsIgnoreCase ( nodeName ) ) {
ret。 add ( xml ) ;
}
}
} catch ( 例外 e ) { }
return ret ;
}
public SimpleXML getNodeByPath ( String nodePath、 boolean createIfNotExists ) {
if ( nodePath == null || nodePath。trim ( ) 。 equalsIgnoreCase ( "" ) )は nullを 返し ます 。
SimpleXML ret = null ;
{
文字列 [ ] bpath = nodePath。 split ( 「 \\ \\ 」 ) ;
if ( bpath != null && bpath。length > 0 ) {
int scnt = 0 ;
for ( int f = 0 ; f < bpath。length ; ++ f ) {
文字列 c = bpath [ f ] トリム ( ) ;
if ( c != null && c。length ( ) > 0 ) scnt ++;
}
if ( scnt > 0 ) {
ret = this ;
for ( int f = 0 ; f < bpath。length ; ++ f ) {
文字列 c = bpath [ f ] トリム ( ) ;
if ( c != null && c。length ( ) > 0 ) {
ベクター< SimpleXML > curnodes = ret。 getChildren ( c ) ;
if ( curnodes != null && curnodes。size ( ) > 0 ) {
ret = curnodes。 firstElement ( ) ;
} else {
if ( createIfNotExists ) {
ret = ret。 createChild ( c ) ;
} else {
ret = null ;
休憩 ;
}
}
}
}
}
}
} catch ( 例外 e ) {
}
return ret ;
}
public static SimpleXML loadXml ( String txxml ) {
SimpleXML ret = null ;
{
ret = SimpleXML。 loadXml ( 新しい ByteArrayInputStream ( txxml。getBytes ( ) ) ) ;
} catch ( 例外 e ) { }
return ret ;
}
public static SimpleXML loadXml ( InputStream isxml ) {
SimpleXML ret = null ;
{
DocumentBuilderFactory dbFactory = DocumentBuilderFactory。 newInstance ( ) ;
DocumentBuilder dbBuilder = dbFactory。 newDocumentBuilder ( ) ;
ドキュメント doc = dbBuilder。 解析 ( isxml ) ;
ret = SimpleXML。 fromNode ( doc。getDocumentElement ( ) ) ;
} catch ( 例外 e ) { }
return ret ;
}
void serializeNode ( XmlSerializer ser ) {
{
ser。 startTag ( "" 、fname ) ;
for (エントリ<文字列、文字列> ee : fattrs。entrySet ( ) ) {
ser。 属性 ( "" 、 ee.getKey ( ) 、 ee.getValue ( ) ) ;
}
if ( fchild。size ( ) > 0 ) {
for ( SimpleXML c : fchild ) {
c。 serializeNode ( ser ) ;
}
} else {
ser。 テキスト ( ftext ) ;
}
ser。 endTag ( "" 、fname ) ;
} catch ( 例外 e ) {
ログ d ( "app" 、 "e:" + e。toString ( ) ) ;
}
}
public static String saveXml ( SimpleXMLドキュメント) {
{
ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ;
XmlSerializer xs = Xml。 newSerializer ( ) ;
xs。 setOutput ( baos、 "Utf-8" ) ;
xs。 startDocument ( "Utf-8" 、 true ) ;
ドキュメント。 serializeNode ( xs ) ;
xs。 endDocument ( ) ;
新しい 文字列を 返す ( baos。toByteArray ( ) ) ;
} catch ( 例外 e ) { }
return "" ;
}
}