異なるスキーマの新着情報をまとたい

「まったく何も分からない・・・」そんなユーザーさんの為のフォーラムです。どんなご質問でもお気軽にどうぞ。
返信
bwmori
記事: 8
登録日時: 2011年9月01日(木) 10:37

異なるスキーマの新着情報をまとたい

投稿記事 by bwmori » 2012年11月01日(木) 14:19

例えば「ニュース」「コラム」「実積紹介」の様に複数のスキーマがあったとして、
それらの最新情報の日付・タイトルのみを日付順に並べて表示する事は可能でしょうか?

例)
2012.11.1 【ニュース】サイトデザイン変更しました。
2012.10.28 【コラム】今日のできごと。
2012.10.27 【実積紹介】●●様案件
2012.10.25 【コラム】今日のできごと。
2012.10.24 【実積紹介】□□様案件

の様に複数のスキーマの内容を1つにまとめて出力できるようにしたいと思っております。
もしくは、javascriptで配列として扱えるようにxmlで出力できますでしょうか。

bwmori
記事: 8
登録日時: 2011年9月01日(木) 10:37

Re: 異なるスキーマの新着情報をまとたい

投稿記事 by bwmori » 2012年11月01日(木) 21:34

XMLで書き出すことによって自己解決できそうなのですが、
出力されたXMLに宣言がないことによってか、
jsで読み込んで出力した際に文字化けしてしまいました。

デザイン定義の
<xsl:output method="xml" encoding="EUC-JP" omit-xml-declaration="no" />
のomit-xml-declarationを"no"にすることで宣言を出力できる様ですが、
PHP側では複数のスキーマから出力しているため、
xmlのタグの間に複数の宣言が入ってしまいます。

うまくxmlの宣言を出力する方法はございませんでしょうか?

webmaster
Site Admin
記事: 1451
登録日時: 2004年12月10日(金) 10:09

Re: 異なるスキーマの新着情報をまとたい

投稿記事 by webmaster » 2012年11月02日(金) 17:58

bwmoriさん、ご質問ありがとうございます。

弊社のほうでも現在、サンプルを作成しているところなのですが、手間取っております。

XML宣言についてですが、ひとつのPHPページに複数のエントリフォルダの出力をまとめてしまう、という方法を試されている、ということでしょうか?
たしかにそれだとAjax通信が1回で済むのでシンプルになって良さそうです。(弊社で作成中のサンプルでは、複数のAjax呼び出しを行っている為、待ち合わせの為の処理が複雑になっております)。

1つめのエントリフォルダで使っているデザイン定義のみ、omit-xml-declarationをnoにして、2つめ以降はyesにする、という方法ではいかがでしょうか?
または、全部yesにした上で、PHPファイル自体にXML宣言を書き込む、という方法もございます(そちらのほうがシンプルかもしれません)。
ただし、PHP側で<?xml? から始まる文字列があると、その部分がPHPスクリプトと判定されてしまう為、以下の方法でXML宣言を出力してください。

<?php echo "<?xml version=\"1.0\" encoding=\"EUC-JP\"?>"; ?>

もし、文字化けが直らない場合、ご利用のAjaxライブラリ側でEUC-JPをうまく処理できていない可能性がございます。
その場合には、リファレンスマニュアルを参考にして、出力文字エンコーディングをUTF-8にした上で、上記のXML宣言もUTF-8に変更してみてください。

bwmori
記事: 8
登録日時: 2011年9月01日(木) 10:37

Re: 異なるスキーマの新着情報をまとたい

投稿記事 by bwmori » 2012年11月02日(金) 19:50

ご回答ありがとうございます。

エントリの出力につきましては、一つのPHPに複数のエントリの出力をまとめております。
文字化けの件につきましては、ご提案頂きましたPHPでの出力でうまく解決できました。

日付順での並び替えにつきましては、出力したXMLを配列に変換するなどの方法があるのでしょうが、
そのあたりの知識が浅いため、
tableで出力し、テーブルの項目にソート機能を付加するjqueryのサンプルを使用して、
日付順に並び変えるようにしました。
(それもクリックごとにソートするものでしたので、javascriptでクリック動作をトリガーで起こして
並び替えをするという力技になってしまいましたが。。。)

一応、表示上は目的通りのページができましたが、
現在サンプルを制作頂いているということでしたので、
もっとスマートな方法があれば助言頂けましたら幸いです。

ありがとうございました。

webmaster
Site Admin
記事: 1451
登録日時: 2004年12月10日(金) 10:09

Re: 異なるスキーマの新着情報をまとたい

投稿記事 by webmaster » 2012年11月06日(火) 01:40

複数のエントリXMLを読み込んでマージするサンプルが出来たことはできたのですが、あまりにも複雑になりすぎた上に、実用性としてはbwmoriさんの作られたような「PHP側で1つのXMLにマージした後、JavaScript側でソートして表示する」という方法のほうが明らかにシンプルで無駄の無い方法と思われますので、サンプルの公開は見合わせたいと思います。

代わりに、bwmoriさんの方法に近いやり方のサンプルを提示させて頂きますので、よろしければご参考までに…。

まずは、以下のようなデザイン定義を使って、各エントリフォルダを「タイトル」と「ジャンプ先URL」と「日付」だけがあるようなシンプルなXMLデータに変換します。
titleとして扱いたい項目を差し替えてください。また、個々のエントリを表示する為のphpページのURLも、対応するものに差し替えてください。

コード: 全て選択

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes" />
<xsl:template match="/entrylist">
<xsl:for-each select="entry">
	<entry>
		<title><xsl:value-of select="title" /></title>
		<date><xsl:value-of select="@date" /></date>
		<href>http://hogehoge/entryA.php<xsl:value-of select="@href" /></href>
	</entry>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
それを、以下のようなPHPページで1つのXMLにマージします。この例では先頭20件ずつマージしています。この時点ではまだソートされていません。

--- merged_entrylist.php ------------------------------

コード: 全て選択

<?php require_once( "cmsdesigner/include/view.php.inc" ); // encoding="utf-8" ?><?php echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; ?>
<entrylist>
<cmsd:entrylist name="エントリフォルダ名1" design="XML出力用のデザイン定義" rows="20"/>
<cmsd:entrylist name="エントリフォルダ名2" design="XML出力用のデザイン定義" rows="20" />
<cmsd:entrylist name="エントリフォルダ名3" design="XML出力用のデザイン定義" rows="20" />
 :
</entrylist>
<?php cmsd_end_template(); ?>
これを、以下のようなJavaScriptで読み込みます。

コード: 全て選択

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta charset="utf-8" />
	<title>JavaScriptでXML化されたエントリを読み込んで日付でソートする</title>
	<style type="text/css">
	
	</style>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
	<script type="text/javascript">
(function(){
	var url = "merged_entrylist.php";
	$.ajax({
		type: "GET",
		url: url,
		dataType: "xml",
		cache : false,
		success: function(xml){
			// XMLからentry要素を抜き出して、jQueryオブジェクト化してentryArr配列に格納
			var entryArr = $(xml).find( "entry" ).map( function(){ 
				return $(this); 
			});
			
			// dateの値で降順にソート
			entryArr.sort( function( a, b ){ 
				var ad = a.find("date").text;
				var bd = b.find("date").text;
				return ( ad < bd ? 1 : ( ad > bd ? -1 : 0 ) );
			});
			
			// HTMLが全て読み込まれるのを待って、#headlineに出力
			$(document).ready( function(){
				var headline = $("#headline");
				$.each( entryArr, function( i, entry ){
					var href = entry.find("href").text();
					var title = entry.find("title").text();
					// li要素として出力
					headline.append( '<li><a href="' + href + '">' + title + '</a></li>' );
				});
			});
		}
	});
})();
	</script>
</head>
<body>
	<h1>JavaScriptでXML化されたエントリを読み込んで日付でソートする</h1>
	<ul id="headline"></ul>
</body>
</html>
 未テストの為、間違いがあったら申し訳ありません。

webmaster
Site Admin
記事: 1451
登録日時: 2004年12月10日(金) 10:09

Re: 異なるスキーマの新着情報をまとたい

投稿記事 by webmaster » 2012年11月06日(火) 01:52

複数のエントリ一覧をXMLで読み込んでマージしてソートするJavaScriptのサンプルですが、公開を見合わせようかと思ったのですが、せっかく作ったので公開しておこうと思います。

デザイン定義については、上とほとんど同じですが、xml宣言を出力している部分が異なります。
titleとして扱いたい項目を差し替えてください。また、個々のエントリを表示する為のphpページのURLも、対応するものに差し替えてください。

コード: 全て選択

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" />
<xsl:template match="/entrylist">
<xsl:for-each select="entry">
   <entry>
      <title><xsl:value-of select="title" /></title>
      <date><xsl:value-of select="@date" /></date>
      <href>http://hogehoge/entryA.php<xsl:value-of select="@href" /></href>
   </entry>
</xsl:for-each>
</xsl:template>
PHP側は、各エントリフォルダ毎に以下のような感じのCMSDタグを指定します。

--- entrylist1.php ------------------------------

コード: 全て選択

<?php require_once( "cmsdesigner/include/view.php.inc" ); // encoding="utf-8" ?>
<cmsd:entrylist name="エントリフォルダ名1" design="XML出力用のデザイン定義" rows="20"/>
<?php cmsd_end_template(); ?>
--- entrylist2.php ------------------------------

コード: 全て選択

<?php require_once( "cmsdesigner/include/view.php.inc" ); // encoding="utf-8" ?>
<cmsd:entrylist name="エントリフォルダ名2" design="XML出力用のデザイン定義" rows="20"/>
<?php cmsd_end_template(); ?>
--- entrylist3.php ------------------------------

コード: 全て選択

<?php require_once( "cmsdesigner/include/view.php.inc" ); // encoding="utf-8" ?>
<cmsd:entrylist name="エントリフォルダ名3" design="XML出力用のデザイン定義" rows="20"/>
<?php cmsd_end_template(); ?>
これを、以下のようなJavaScriptで読み込みます。

コード: 全て選択

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<meta charset="utf-8" />
	<title>JavaScriptで複数のコンテンツのエントリを読み込んでマージ後、日付順にソートする</title>
	<style type="text/css">
	
	</style>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
	<script type="text/javascript">
(function(){
	// ★ここでエントリ一覧XMLのURLを複数指定する
	var urls = [
		"entrylist1.php",
		"entrylist2.php",
		"entrylist3.php"
	];
	
	// エントリの配列をここに読み込む
	var entryArr = [];
	
	// 指定されたURLをajaxでロードし、そのDeferredオブジェクトを返す関数
	var createAjaxDeferred = function( url ){
		var def = $.Deferred();
		$.ajax({
			type: "GET",
			url: url,
			dataType: "xml",
			cache : false,
			success: function(xml){
				def.resolve(xml);
			},
			error : function(){
				def.resolve( null );
			}
		});
		return def;
	};
	
	// URLの配列を、そのURLをajax読み込みするDeferredオブジェクトの配列に変換
	var defs = $.map( urls, createAjaxDeferred )
	
	// Deferredの配列が全て完了したら、entryArr配列に結果を格納する
	$.when.apply( $, defs ).then( function(){
		for( var i = 0; i < arguments.length; i++ )
		{
			// arguments[i]は、各URLから読み込んだXMLオブジェクト
			$(arguments[i]).find( "entry" ).each( function(){
				// XMLからentry要素を抜き出して、jQueryオブジェクト化してentryArr配列に格納
				var entry = $(this);
				entryArr.push( entry );
			});
		}
		
		// HTMLドキュメント全体が読み込まれるまで待つ
		$(document).ready( function(){
			// 日付でソート
			entryArr.sort( function( a, b ){ 
				var ad = a.find("date").text;
				var bd = b.find("date").text;
				return ( ad < bd ? 1 : ( ad > bd ? -1 : 0 ) );
			});
			
			// 全てのエントリをHTMLに書き出す(ul要素の#headlineへ)
			var headline = $("#headline");
			$.each( entryArr, function( i, entry ){
				var href = entry.find("href").text();
				var title = entry.find("title").text();
				// ★li要素として出力
				headline.append( '<li><a href="' + href + '">' + title + '</a></li>' );
			});	
		});
	});
})();
	
	</script>
</head>
<body>
	<h1>JavaScriptで複数のコンテンツのエントリを読み込んでマージ後、日付順にソートする</h1>
	<ul id="headline"></ul>
</body>
</html>

返信