XMLを操作するためのシンプルなクラス

まえがき


むかしむかし、「ドキュメントオブジェクトモデル」という問題に遭遇しました。 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、 0z。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 "" ;
}
}

Source: https://habr.com/ru/post/J91845/


All Articles