iT邦幫忙

0

利用javascript去xml抓取多筆資料

我有很多筆下面那樣的資料

<mane01>0</mane>
<type>text</type>
<title>01</title>
<mane02>1</mane>
<type>text</type>
<title>02</title>
<mane03>2</mane>
<type>val</type>
<title>03</title>

他們被寫在同一個xml裡,我利用下面方法抓取該xml中的類型

var miscellaneous = new HandleXml();
Info.setUrl("../xml/text.xml");
var InfoInfo = Info.getNodeValue("type");

我需要將同類型的title顯示在ID=se的select中供選擇

<select id="se"></select>

目前我只會抓單筆,但我最終結果需要抓多筆,請問我能怎麼做?

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
ccutmis
iT邦高手 2 級 ‧ 2019-04-30 15:47:09
最佳解答

我把樓主的xml格式稍作修改如下:
01.xml

<manes>
	<mane>
		<mindex>0</mindex>
		<type>text0</type>
		<title>01</title>
	</mane>
	<mane>
		<mindex>1</mindex>
		<type>text1</type>
		<title>02</title>
	</mane>
	<mane>
		<mindex>2</mindex>
		<type>text2</type>
		<title>03</title>
	</mane>
</manes>

再來是html+javascript的部份,這邊有用到jquery處理load xml file & parsing:
test.htm

<!doctype html>
<html><head>
<meta charset="utf-8">
<title>jQuery讀取xml並轉陣列或直接處理</title>
<script
 src="https://code.jquery.com/jquery-3.4.0.min.js"
 integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg="
 crossorigin="anonymous"></script>
</head>
<body>
<label>Manes:</label><select id="se"></select>
<script>
 var tmpIndex=[], tmpType=[], tmpTitle=[]; //這行非必要只是測試把xml內容塞入陣列
 var tmpOptionStr='';
 $.ajax({
	url: './01.xml',
	type: 'GET', 
	dataType: 'xml',
	success: function(returnedXMLResponse){
		$('mane', returnedXMLResponse).each(function(){
			tmpIndex.push($('mindex', this).text()); //這行非必要只是測試把xml內容塞入陣列
			tmpType.push($('type', this).text()); //這行非必要只是測試把xml內容塞入陣列
			tmpTitle.push($('title', this).text()); //這行非必要只是測試把xml內容塞入陣列
			tmpOptionStr+='<option value="'+$('mindex', this).text()+'">'+$('title', this).text()+' '+$('type', this).text()+'</option>';
		});
		console.log(tmpOptionStr);
		$('#se').html(tmpOptionStr);
	}  
}); 
</script>
</body>
</html>

var tmpIndex=[], tmpType=[], tmpTitle=[];
tmpIndex.push($('mindex', this).text());
tmpType.push($('type', this).text());
tmpTitle.push($('title', this).text());
這四行沒有也沒關係,只是順便列出把xml轉成陣列的方式給樓主參考,轉成陣列後要用迴圈抓內容就是桌上抓橘的事了,例如:

for(var i=0;i<tmpIndex.length;i++){
    tmpStr+='<option value="'+tmpIndex[i]+'"'>+tmpTitle[i]+' '+tmpTitle[i]+'</option>';
}

https://ithelp.ithome.com.tw/upload/images/20190430/20028574jvSQw1vEFd.png
提外話,如果可以的話把xml內容格式改成json會更好,以01.xml內容為例,轉成01.json變成:

{{'mindex':0,'type':'text0','title:'01'},{'mindex':1,'type':'text1','title:'02'},{'mindex':2,'type':'text2','title:'03'}}

對enduser來說同樣的內容,下載檔案size卻小很多,當然改用json存取的方式要改寫,但不會很難就是了,提供您參考。

看更多先前的回應...收起先前的回應...
<manes>
	<mane1>
		<mindex>0</mindex>
		<type>text</type>
		<title>01</title>
	</mane1>
	<mane2>
		<mindex>1</mindex>
		<type>text</type>
		<title>02</title>
	</mane2>
	<mane3>
		<mindex>2</mindex>
		<type>id</type>
		<title>03</title>
	</mane3>
</manes>

嚴格來說應該會是這樣的形態,type會有重複的,我要顯示一樣type的title,但我目前寫的都會全部顯示/images/emoticon/emoticon02.gif

ccutmis iT邦高手 2 級 ‧ 2019-04-30 16:26:50 檢舉

那個標籤本來就不應該這樣寫

<mane01>...</mane01>
<mane02>...</mane02>

要改成

<mane>...<title>01</title></mane>
<mane>...<title>02</title></mane>

這樣才有辦法去取得所有<mane>裡面的東西,
寫成<mane+遞增數字>應該還是有辦法,但是不建議,因為那是繞遠路的作法,你應該做的是改寫產出xml的程式,讓它排列出適用的格式。

ccutmis iT邦高手 2 級 ‧ 2019-04-30 16:33:16 檢舉

"嚴格來說應該會是這樣的形態,type會有重複的,我要顯示一樣type的title,但我目前寫的都會全部顯示"
這個我看不太懂你說的意思,能附個圖片描述嗎?

xml的內容我這邊無法做修改,那是FW做出來的結果,所以才會比較麻煩,如果必須要繞遠路的話我也只能繞了
而"嚴格來說應該會是這樣的形態,type會有重複的,我要顯示一樣type的title,但我目前寫的都會全部顯示"拿我上面第一個留言的內容來說就是指有3筆資料,但我只顯示type為text的資料或者type為id的資料這樣,但我做出來的結果都與大大你做出來的結果一樣是全部都顯示。

ccutmis iT邦高手 2 級 ‧ 2019-04-30 16:54:43 檢舉

FW是什麼?

全部都顯示是因為我沒設過濾條件啊(就是單純把全部節點跑一遍),
你寫的:”我要顯示一樣type的title”,
我還是看不懂,是type都等於"text"的列出來還是type要等於什麼呢,
有明確的定義才有辦法設過濾條件。_。

ccutmis iT邦高手 2 級 ‧ 2019-04-30 17:11:00 檢舉

作了一點點改寫 加上判斷如果type=="text"就會在第一個select裡,如果不是就會在第二個select裡,這樣是類似你要的結果嗎?
test.htm

<!doctype html>
<html><head>
<meta charset="utf-8">
<title>jQuery讀取xml並轉陣列或直接處理</title>
<script
 src="https://code.jquery.com/jquery-3.4.0.min.js"
 integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg="
 crossorigin="anonymous"></script>
</head>
<body>
<label>Manes_TEXT:</label><select id="seType"></select>
<label>Manes_ID:</label><select id="seId"></select>
<script>
 var tmpStrType='',tmpStrId='';
 $.ajax({
	url: './01.xml',
	type: 'GET', 
	dataType: 'xml',
	success: function(returnedXMLResponse){
		$('mane', returnedXMLResponse).each(function(){
			if($('type', this).text()=='text'){
				tmpStrType+='<option value="'+$('mindex', this).text()+'">'+$('title', this).text()+' '+$('type', this).text()+'</option>';
			}else{
				tmpStrId+='<option value="'+$('mindex', this).text()+'">'+$('title', this).text()+' '+$('type', this).text()+'</option>';
			}
		});
		$('#seType').html(tmpStrType);
		$('#seId').html(tmpStrId);
	}
}); 
</script>
</body>
</html>

01.xml

<manes>
	<mane>
		<mindex>0</mindex>
		<type>text</type>
		<title>01</title>
	</mane>
	<mane>
		<mindex>1</mindex>
		<type>text</type>
		<title>02</title>
	</mane>
	<mane>
		<mindex>2</mindex>
		<type>id</type>
		<title>03</title>
	</mane>
</manes>

https://ithelp.ithome.com.tw/upload/images/20190430/20028574qGJIRwox74.png

<type></type>內的文字不一樣,像下面這段中的<type></type>內的文字內容有text跟id,mane也並非是<mane></mane>這樣,而是
<mane1></mane1><mane2></mane2>...這樣的寫法

<manes>
	<mane1>
		<mindex>0</mindex>
		<type>text</type>
		<title>01</title>
	</mane1>
	<mane2>
		<mindex>1</mindex>
		<type>text</type>
		<title>02</title>
	</mane2>
	<mane3>
		<mindex>2</mindex>
		<type>id</type>
		<title>03</title>
	</mane3>
</manes>

而我想做的是將xml中所有資料中<type></type>內容一樣的資料顯示出來

var Info = new HandleXml();
Info.setUrl("../test.xml");
var x = Info.getNodeValue("type");
if(x == "text"){
    ...//show資料
} //這判斷式用在mane後未加編號時

是的,大大後來寫的code類似我要的結果,非常感謝您。

剛剛忘了還有一個問題,<mane></mane>部分若是mane+編號的話$('mane', returnedXMLResponse).each(function(){...}部分我該怎麼改??在外層加與for(var a=0; a<tmpIndex.length; a++){...}類似的迴圈就好嗎?

ccutmis iT邦高手 2 級 ‧ 2019-04-30 17:43:00 檢舉

修改好的demo您參考看看:
大部份都沒有改到,主要是在讀入xml時,把xml轉成str,然後用RegExp把<mane數字></mane數字>置換成<mane></mane>,再把處理好的str轉成xml物件...以下略。
test.htm

<!doctype html>
<html><head>
<meta charset="utf-8">
<title>jQuery讀取xml並轉陣列或直接處理</title>
<script
 src="https://code.jquery.com/jquery-3.4.0.min.js"
 integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg="
 crossorigin="anonymous"></script>
</head>
<body>
<label>Manes_TEXT:</label><select id="seType"></select>
<label>Manes_ID:</label><select id="seId"></select>
<script>
function xmlToString(xmlData) { 
	var xmlString;
	//IE
	if (window.ActiveXObject){
		xmlString = xmlData.xml;
	}
	else{
		xmlString = (new XMLSerializer()).serializeToString(xmlData);
	}
	return xmlString;
} 

 var tmpStrType='',tmpStrId='';
 $.ajax({
	url: './01.xml',
	type: 'GET', 
	dataType: 'xml',
	success: function(returnedXMLResponse){
		xmlStr=xmlToString(returnedXMLResponse);
		console.log('原本的xml內容:\n'+xmlStr);
		xmlStr=xmlStr.replace(/mane\d{1,2}>/g, "mane>");
		console.log('\n修改標籤後的xml內容:\n'+xmlStr);
		newXml=$.parseXML(xmlStr);

		$('mane', newXml).each(function(){
			if($('type', this).text()=='text'){
				tmpStrType+='<option value="'+$('mindex', this).text()+'">'+$('title', this).text()+' '+$('type', this).text()+'</option>';
			}else{
				tmpStrId+='<option value="'+$('mindex', this).text()+'">'+$('title', this).text()+' '+$('type', this).text()+'</option>';
			}
		});
		$('#seType').html(tmpStrType);
		$('#seId').html(tmpStrId);
	}
}); 
</script>
</body>
</html>

01.xml

<manes>
	<mane1>
		<mindex>0</mindex>
		<type>text</type>
		<title>01</title>
	</mane1>
	<mane2>
		<mindex>1</mindex>
		<type>text</type>
		<title>02</title>
	</mane2>
	<mane3>
		<mindex>2</mindex>
		<type>id</type>
		<title>03</title>
	</mane3>
</manes>
0
舜~
iT邦高手 1 級 ‧ 2019-04-30 10:49:40

大大請問迴圈有類似的範例能參考嗎??

0
froce
iT邦大師 1 級 ‧ 2019-05-01 12:30:52

為了練習一下JS寫的。
xml可以讓browser去解析,應該不用用到regex。
然後其實用JQ搞不好更快。

chrome、firefox等現代瀏覽器only。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <select id="text-select"></select>
</body>
</html>

<script>
    var xhttp = new XMLHttpRequest();
    
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            
            // 去除掉純文字節點
            var manes = Array.from(this.responseXML.querySelector("manes").childNodes).filter(elm => elm.nodeName != "#text")
            
            // 將節點轉換成JSON
            var result = manes.map(function(elm){
                var children = Array.from(elm.childNodes).filter(elm => elm.nodeName != "#text")
                var temp = {}
                for (var child of children){
                    temp[child.nodeName] = child.innerHTML
                }
                return temp
            })
            
            // 對array內每個object處理,產生option
            result.filter(o => o.type == "text").map(o => {
                var select = document.getElementById("text-select")
                var option = document.createElement("option")
                option.innerText = o.title
                option.setAttribute("mindex", o.mindex)
                select.appendChild(option)
            })

        }
    };
    
    xhttp.open("GET", "./01.xml", true);
    xhttp.send();
</script>

我要發表回答

立即登入回答