Outlook 2007 のインポート機能だと、フォルダが1階層だけになっちゃうんですもの。
こいつはフォルダ階層を維持して取り込みます。
type=rss でない outline 要素をフォルダと認識します。
type=include および type=link かつファイル名の末尾が .opml のものは再帰的に展開します。
共通フィードリストは、フィード名と同じ名前のファイルを内部的に生成するので、ファイル名に使えない文字をフィード名にすると落ちます。
そのため、フィード名のクリーンアップ処理も行っています。
<?xml version="1.0" encoding="UTF-16" standalone="yes" ?>
<job>
<runtime>
<description>OPML ファイルから Windows の共通フィード ストアにフィードをインポートします。</description>
<named name="opml" helpstring="インポートする OPML の URI" type="string" required="true"/>
<example>例:import.wsf http://www.example.com/feeds.opml</example>
</runtime>
<script language="JavaScript">
<![CDATA[
String.prototype.startsWith = function( str )
{
if ( this.length < str.length ) { return false; }
return ( this.substring( 0, str.length ) == str );
};
String.prototype.endsWith = function( str )
{
if( this.length < str.length ) { return false; }
return ( this.substring( this.length - str.length ) == str );
};
function /* string */ getFeedTitle( /* string */ feedUri )
{
var xmlDom = WScript.CreateObject( "Microsoft.XMLDOM" );
xmlDom.async = false;
xmlDom.load( feedUri );
var docElt = xmlDom.documentElement;
if( docElt.baseName == "RDF" && docElt.namespaceURI == "http://www.w3.org/1999/02/22-rdf-syntax-ns#" )
{
// RSS 1.0
var channel = docElt.selectSingleNode( "./channel" );
if( channel.namespaceURI == "http://purl.org/rss/1.0/" )
{
return channel.selectSingleNode( "./title" ).text;
}
}
else if( docElt.baseName == "rss" && docElt.getAttribute( "version" ) == "2.0" )
{
// RSS 2.0
var channel = docElt.selectSingleNode( "./channel" );
return channel.selectSingleNode( "./title" ).text;
}
else
{
// Unknown format
}
return null;
}
function /* string */ cleanupFileName( /* string */ fileName )
{
fileName = fileName.replace( /[\x00-\x19]/, " " );
fileName = fileName.replace( "\\", "¥" );
fileName = fileName.replace( "/", "/" );
fileName = fileName.replace( ":", ":" );
fileName = fileName.replace( "*", "*" );
fileName = fileName.replace( "?", "?" );
fileName = fileName.replace( '"', '”' );
fileName = fileName.replace( "<", "<" );
fileName = fileName.replace( ">", ">" );
fileName = fileName.replace( "|", "|" );
return fileName;
}
function importFeedsInternal( /* XMLDOMNodeList */ outlines, /* FeedFolder */ folder )
{
for( var i = 0; i < outlines.length; ++i )
{
var outline = outlines.item( i );
var type = outline.getAttribute( "type" );
var text = outline.getAttribute( "text" );
if( text != null )
{
text = cleanupFileName( text );
}
if( type == "rss" )
{
var url = outline.getAttribute( "xmlUrl" );
if( text == null )
{
text = getFeedTitle( url );
}
var feed = null;
if( folder.ExistsFeed( text ) )
{
feed = folder.GetFeed( text );
}
if( feed == null )
{
feed = folder.CreateFeed( text, url );
}
else if( feed.Url != url )
{
feed.Url = url;
}
}
else
{
var subfolder = null;
if( folder.ExistsSubfolder( text ) )
{
subfolder = folder.GetSubfolder( text );
}
if( subfolder == null )
{
subfolder = folder.CreateSubfolder( text );
}
var url = outline.getAttribute( "url" );
if( type == "include" || ( type == "link" && url.endsWith( ".opml" ) ) )
{
importFeeds( url, subfolder );
}
importFeedsInternal( outline.selectNodes( "./outline" ), subfolder );
}
}
}
function importFeeds( /* string */ opml, /* FeedFolder */ folder )
{
var xmlDom = WScript.CreateObject( "Microsoft.XMLDOM" );
xmlDom.async = false;
xmlDom.load( opml );
var outlines = xmlDom.selectNodes( "/opml/body/outline" );
importFeedsInternal( outlines, folder );
}
if( WScript.Arguments.Named.Exists( "opml" ) == 0 )
{
WScript.Arguments.ShowUsage();
WScript.Quit();
}
var opml = WScript.Arguments.Item( 0 );
if( ! opml.startsWith( "/opml:" ) || opml.length <= "/opml:".length )
{
WScript.Arguments.ShowUsage();
WScript.Quit();
}
opml = opml.substring( "/opml:".length );
var feedManager = WScript.CreateObject( "Microsoft.FeedsManager" );
importFeeds( opml, feedManager.RootFolder );
]]>
</script>
</job>