#!/usr/bin/perl
use utf8;
use warnings;
use XML::LibXML;
use Encode qw/encode decode/;
#変換するICMLファイルのパスを取得
my $convertIcmlFilePath = $ARGV[0];
$convertIcmlFilePath = decode('UTF-8', $convertIcmlFilePath);
#パース実行
my $parser = XML::LibXML->new();
$parser->no_network(1);
my $dom = $parser->parse_file($convertIcmlFilePath);
######### DOM置換 #########
foreach my $paragraphStyleRange($dom->findnodes('//ParagraphStyleRange')){
#既定の段落スタイルの値を保存
my $appliedParagraphStyle = $paragraphStyleRange->findvalue('@AppliedParagraphStyle');
#最終置き換え用ノード定義
my $repleceParagraphStyleRangeNode = XML::LibXML::Element->new( "ParagraphStyleRange" );
$repleceParagraphStyleRangeNode->setAttribute( "AppliedParagraphStyle", $appliedParagraphStyle );
#子ノードをリストで取得
my @paragraphStyleRangeChildNodes = $paragraphStyleRange->childNodes;
#置換後の中身の配列を定義
my @replacedParagraphStyleRangeChildNodes;
#CharacterStyleRange処理用サブルーチンに処理を投げる
foreach $paragraphStyleRangeChildNode (@paragraphStyleRangeChildNodes){
my $type = $paragraphStyleRangeChildNode->nodeType;
if ($type == 1){
my $name = $paragraphStyleRangeChildNode->nodeName;
#エレメントノードでCharacterStyleRangeノードだった場合サブルーチンに処理を投げて結果を得、順番に配列にPush
if ($name eq "CharacterStyleRange"){
my @replacedNodes = & replaceCharacterStyleRangeNodes($paragraphStyleRangeChildNode);
foreach (@replacedNodes) {push(@replacedParagraphStyleRangeChildNodes,$_)};
} else {
#エレメントノードでCharacterStyleRangeノードでなかった場合はそのまま配列にPush
push (@replacedParagraphStyleRangeChildNodes,$paragraphStyleRangeChildNode);
}
} else {
#エレメントノードでなかった場合はそのまま配列にPush
push (@replacedParagraphStyleRangeChildNodes,$paragraphStyleRangeChildNode);
}
}
#新たに作った$paragraphStyleRangeノードに子ノード流し込み
foreach(@replacedParagraphStyleRangeChildNodes){$repleceParagraphStyleRangeNode->appendChild( $_ )}
#元の$paragraphStyleRangeノードと新しく作ったヤツの置換を実行
$paragraphStyleRange->replaceNode($repleceParagraphStyleRangeNode);
}
######### 出力処理 #########
#ノードをシリアライズして文字列に
my $documents = $dom->findnodes('//Document');
my $serializedTxt = $$documents[0]->serialize;
#ヘッダ付加
my $mergedTxt = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' . "\x0A" . '<?aid style="50" type="snippet" readerVersion="6.0" featureSet="513" product="8.0(370)" ?>' . "\x0A" . '<?aid SnippetType="InCopyInterchange"?>' . "\x0A" . $serializedTxt;
#後処理整形
$mergedTxt =~ s@</CharacterStyleRange><CharacterStyleRange@</CharacterStyleRange>\x0A<CharacterStyleRange@g;
$mergedTxt =~ s@\x0A@\x0D\x0A@g;
#出力実行
$mergedTxt = encode('UTF-8', $mergedTxt);
open(OUT,"> $convertIcmlFilePath");
print OUT $mergedTxt;
close (OUT);
exit;
######### CharacterStyleRange処理サブルーチン #########
sub replaceCharacterStyleRangeNodes {
#引数の取得
my $originalCharacterStyleRangeNode = $_[0];
#既定の文字スタイルの値を保存
my $appliedCharacterStyle = $originalCharacterStyleRangeNode->findvalue('@AppliedCharacterStyle');
#子ノードをリストで取得
my @characterStyleRangeChildNodes = $originalCharacterStyleRangeNode->childNodes;
#置換後の中身の配列を定義
my @replacedNodes;
#Content処理用サブルーチンに処理を投げる
foreach $characterStyleRangeChildNode(@characterStyleRangeChildNodes){
my $type = $characterStyleRangeChildNode->nodeType;
if ($type == 1){
my $name = $characterStyleRangeChildNode->nodeName;
#エレメントノードでContentノードだった場合中身をsplitしてルビ部分とそうじゃないやつを分けて、順番にCharacterStyleRangeノードでくるんで配列にPush
if ($name eq "Content"){
$contentValue = $characterStyleRangeChildNode->textContent;
my @splitContentsArray = split(/({.*?})/, $contentValue);
foreach $splitContent (@splitContentsArray){
#ルビタグブロックだった場合の処理
if ($splitContent =~ /^{([^\|]+?)\|(.+?)}$/){
#親字のブロックとルビのブロックに分割して処理
my $rbBlock = $1;
my $rtBlock = $2;
my $rbBlockLength = length($rbBlock);
my @rtBlockArray = split(/\|/, $rtBlock);
#親字ブロックの文字数がルビブロックの分割数と一致していたらモノルビとして処理
if ($rbBlockLength == scalar(@rtBlockArray)){
my $repleceCharacterStyleRangeNode = XML::LibXML::Element->new( "CharacterStyleRange" );
$repleceCharacterStyleRangeNode->setAttribute( "AppliedCharacterStyle", $appliedCharacterStyle );
$repleceCharacterStyleRangeNode->setAttribute( "RubyFlag", "1" );
my $joinedMonoRubyString = join(" ", @rtBlockArray);
$repleceCharacterStyleRangeNode->setAttribute( "RubyString", $joinedMonoRubyString );
my $newContentNode = XML::LibXML::Element->new( "Content" );
$newContentNode->appendTextNode( $rbBlock );
$repleceCharacterStyleRangeNode->appendTextNode( "\x0A" );
$repleceCharacterStyleRangeNode->appendChild( $newContentNode );
$repleceCharacterStyleRangeNode->appendTextNode( "\x0A" );
push (@replacedNodes,$repleceCharacterStyleRangeNode);
} else {
#親字ブロックの文字数がルビブロックの分割数と一致しなければグループルビとして処理
my $repleceCharacterStyleRangeNode = XML::LibXML::Element->new( "CharacterStyleRange" );
$repleceCharacterStyleRangeNode->setAttribute( "AppliedCharacterStyle", $appliedCharacterStyle );
$repleceCharacterStyleRangeNode->setAttribute( "RubyFlag", "1" );
my $joinedGroupRubyString = join("", @rtBlockArray);
$repleceCharacterStyleRangeNode->setAttribute( "RubyString", $joinedGroupRubyString );
$repleceCharacterStyleRangeNode->setAttribute( "RubyType", "GroupRuby" );
my $newContentNode = XML::LibXML::Element->new( "Content" );
$newContentNode->appendTextNode( $rbBlock );
$repleceCharacterStyleRangeNode->appendTextNode( "\x0A" );
$repleceCharacterStyleRangeNode->appendChild( $newContentNode );
$repleceCharacterStyleRangeNode->appendTextNode( "\x0A" );
push (@replacedNodes,$repleceCharacterStyleRangeNode);
}
#ルビタグブロックでなかった場合の処理
} else {
my $repleceCharacterStyleRangeNode = XML::LibXML::Element->new( "CharacterStyleRange" );
$repleceCharacterStyleRangeNode->setAttribute( "AppliedCharacterStyle", $appliedCharacterStyle );
my $newContentNode = XML::LibXML::Element->new( "Content" );
$newContentNode->appendTextNode( $splitContent );
$repleceCharacterStyleRangeNode->appendTextNode( "\x0A" );
$repleceCharacterStyleRangeNode->appendChild( $newContentNode );
$repleceCharacterStyleRangeNode->appendTextNode( "\x0A" );
push (@replacedNodes,$repleceCharacterStyleRangeNode);
}
}
} else {
#エレメントノードでContentノードでなかった場合はそのままCharacterStyleRangeノードでくるんで配列にPush
my $repleceCharacterStyleRangeNode = XML::LibXML::Element->new( "CharacterStyleRange" );
$repleceCharacterStyleRangeNode->setAttribute( "AppliedCharacterStyle", $appliedCharacterStyle );
$repleceCharacterStyleRangeNode->appendTextNode( "\x0A" );
$repleceCharacterStyleRangeNode->appendChild( $characterStyleRangeChildNode );
$repleceCharacterStyleRangeNode->appendTextNode( "\x0A" );
push (@replacedNodes,$characterStyleRangeChildNode);
}
} else {
#エレメントノードでなかった場合はそのまま配列にPush
push (@replacedNodes,$characterStyleRangeChildNode);
}
}
return @replacedNodes;
}