2017年8月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
無料ブログはココログ

2017年7月30日 (日)

IEのCOMインターフェイスでSJISとかUTF-8をOnMemoryで表示させる方法

プログラムから(ファイルを使わないで)IEを起動しXMLを開く方法からの派生。

IEのCOMインターフェイスで、OnMemoryからIEで表示する方法としてMSHTML::HTMLDocument2::write(BSTR)を提示したが、BSTRで渡すIFである以上、UNICODE(UTF-16)=WideCharしか渡せないので、SHIFT-JISやUTF-8のようなMultiByteコードで表示できなかった。
これで何が問題になるかというと、inputタグに漢字コードを渡すhiddenなやつがあるとURLエンコードの結果がエンコードに引っ張られてUTF-8のみに固定されてしまったのだ。(なぜUTF-16にならないのかはよくわかっていないが、javascriptがUTF-8前提になっているのでHTML界隈ではUTF-8で扱うことになっているのだろう?)
んで、BSTR型ではない方法で、IEに内容を渡すIFがないのか探していたのだが、(お仕事で実装がほとんど終わったこの時期に)やり方を見つけた。

↓ここを参考にしましたんで、詳細はこちらを参照してください。
Loading HTML content from a Stream

※:GlobalFree()で解放例外が出るなーと思っていたら、CreateStreamOnHGlobal()の第二引数をfalseにしないとダメじゃないですか?

Visual Studio 2017からVisual C++  Win32コンソールアプリケーションから作成(文字セットをUNICODEから設定なしにしておく)。

#include "stdafx.h"
//#include <Strsafe.h>
#include <stdio.h>
#include <tchar.h>

#import <shdocvw.dll>
#import <mshtml.tlb>

bool writeHtml(SHDocVw::IWebBrowser2Ptr &pIE, const TCHAR* pszHTMLText)
{
bool ret = false;

HRESULT hr;
IStream* pStream = NULL;
IDispatch* pHtmlDoc = NULL;
IPersistStreamInit* pPersistStreamInit = NULL;

MSHTML::IHTMLDocument2Ptr pDoc(pIE->Document);
//if (pDoc == nullptr) {
if (pDoc == NULL) {
goto FUNC_END;
}

//size_t cchMax = 256;
size_t cchLength = _tcslen(pszHTMLText);
HGLOBAL hHTMLText = GlobalAlloc(GPTR, cchLength + 1);
if (hHTMLText == NULL) {
goto FUNC_END;
}
//StringCchCopy((TCHAR*)hHTMLText, cchLength + 1, pszHTMLText);
_tcscpy_s((TCHAR*)hHTMLText, cchLength + 1, pszHTMLText);
hr = CreateStreamOnHGlobal(hHTMLText, FALSE, &pStream);
if (FAILED(hr)) {
goto FUNC_END;
}

// Call the helper function to load the browser from the stream.
// Query for IPersistStreamInit.
hr = pDoc->QueryInterface(IID_IPersistStreamInit, (void**)&pPersistStreamInit);
if (FAILED(hr)) {
goto FUNC_END;
}

// Initialize the document.
hr = pPersistStreamInit->InitNew();
if (FAILED(hr)) {
goto FUNC_END;
}

// Load the contents of the stream.
hr = pPersistStreamInit->Load(pStream);
if (FAILED(hr)) {
goto FUNC_END;
}

ret = true;

FUNC_END:
pPersistStreamInit->Release();
pStream->Release();
//pDoc->Release();
pDoc->close();
GlobalFree(hHTMLText);

return ret;
}

// IEを起動してhtmlデータを書き込む
// IEをコントロールしたい(IEを閉じるなど)場合は、WebBrowserのインスタンスを外に出して管理した方がよい
void openIE(const TCHAR* pszHTMLText)
{
SHDocVw::IWebBrowser2Ptr pIE;

// IE 起動+HTMLデータ設定+表示
HRESULT hr = pIE.CreateInstance(__uuidof(SHDocVw::InternetExplorer));
if (FAILED(hr)) {
return;
}

pIE->Navigate(L"about:blank"); //何か設定しないでHTMLを書き込むと例外が発生する。空文字を入れると"http:///"となる

bool bRslt = writeHtml(pIE, pszHTMLText);
if (!bRslt)
{
return;
}
pIE->Visible = VARIANT_TRUE; // IEを表示状態にする。ここで見えるようになる。

pIE = NULL;
}

int main(int argc, char* argv[])
{
int rtn = -1;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwFileSize = 0;
TCHAR* fileData = NULL;

HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);

if (argc != 2) {
fprintf(stderr,
"INVALID ARGUMENT.\n"
" Please Input HTML FileName(FULL PATH).\n"
);
goto FUNC_END;
}

hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
goto FUNC_END;
}
dwFileSize = GetFileSize(hFile, NULL);
fileData = new TCHAR[dwFileSize + 1];
DWORD dwReadSize = 0;
BOOL bRslt = ReadFile(hFile, (LPVOID)fileData, dwFileSize, &dwReadSize, NULL);
if (!bRslt) {
goto FUNC_END;
}
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
fileData[dwFileSize] = '\0';

openIE(fileData);
rtn = 0;

FUNC_END:
if (fileData != NULL) {
delete[]fileData;
}
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
}
::CoUninitialize();

return rtn;

確認したHTMLファイルは以下。それぞれSHIFT-JISとUTF-8de保存し、引数にファイル名を設定すればOK
なお、UNICODE(UTF-16)で保存されたファイルはNG。
●sjis.html

<html>
<head>
<meta charset="SHIFT_JIS">
</head>
<body>
文字コード:SJIS
</body>
</html>

●utf8.html

<html>
<head>
<meta charset="UTF-8">
</head>
<body>
文字コード:UTF-8
</body>
</html>

2017年6月11日 (日)

文字コードについて(主にWindows)

お仕事で、文字コードに苦しんだのでちょっと調べてみた。
ファイル出力されたUNICODE(UTF-8)、Windowsアプリ内でBSTRやら_bstr_tやらの扱いが混乱してしまった。あと、WideChar、マルチバイト文字、2バイト文字とか。
文字コードで一般的に頭に思い浮かべるのはASCII、SHIFT-JIS、UTF-8。UNICODEも。UNICODEとUTF-8、UTF-16とかの違いは?EUC-JPってのもある。

つらつらと書きだしてみる。。

  • UNICODEとUTF-8について。
    UNICODEは、符号化文字集合や文字符号化方式を定めたもの。
  • 符号化文字集合は、文字に対する数値が割り振られたもの(論理コードとでもいうべきか)。文字コード、コードセット、キャラセット、CES。UNICODEは、U+0000~U+10ffffとか表記される。”犬”は、UNICODEでU+72ac
  • 文字符号化方式は、符号化文字集合をバイト列に扱う仕様、方法を記したもの(物理コードという感じ?)。エンコーディング、CEF。UTF-8は、UNICODEの符号化文字集合の一つで1~4バイトで表現される。”犬”をUTF-8でバイト列にすると0xe78aac。UTF-16だと0x72ac。SHIFT-JISだと0x8ca2。
    ASCII文字類はUTF-8・UTF-16だと0x00を加えて2バイトにする。
  • BSTRは、内部でWideCharで扱われる。正確に言うと、OLECHAR *であり、OLECHARはWIN32であるとき+OLE2ANSIではないときにWCHARとなる。それ以外の時はchar型となる。
  • _bstr_tは、BSTRのスマートポインタ、ヘルパークラス。デバッグで見るとメンバ変数を見ると、m_wstrメンバ変数(BSTR)とm_strメンバ変数(mutable char*)、m_RefCount(unsigned long:スマートポインタのカウンタ)がある。
    _bstr_tの変数を作ると、m_wstrメンバ変数にUTF-16(WideCharな 2バイト文字)で格納される。(const char*)でキャストするとm_strメンバ変数に新たに領域を確保してからロケールに従った変換結果(日本ならSHIFT-JISのマルチバイト)を格納する。変数の参照が終わると領域を解放する。
    ちなみに、DLL内の関数に_bstr_t変数を渡して(const char*)でキャストすると、_bstr_t変数のスコープ外にでたときに領域解放できない。EXEとDLLのメモリ空間が異なるため。BSTRで渡してDLL内部で変換するべき。
  • UNICODE(WideChar)をUTF-8やSHIFT-JIS(マルチバイト)に変換するには、WindowsAPIではWideCharToMultiByte()を使う。その逆はMultiByteToWideChar()を使う。UTF-8とSHIFT-JISの変換は、いったんUNICODE(WideChar)に変換してから、変換したい文字コード(マルチバイト)にする。
  • BSTRからロケールに合わせた文字コードにするにはOLE2T、W2Aとか使えるかも。MSDN「ATLとMFCの文字列変換マクロ」を参照のこと。

テキストエディタで保存した、SHIFT-JIS、UTF-8、UTF-16、UTF-16(BigEndian)をVisualStudioでバイナリとして開いてみると以下のようになる。UTF-8,16,16(BE)の先頭3バイトはBOMが付いている。

Photo

試してみたプログラム

// TestBSTR.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"comsuppw.lib")	// WideChar (link comsuppw.lib)
//#pragma comment(lib,"comsupp.lib")	// Not WideChar (link comsupp.lib)

#include "stdafx.h"
#include <windows.h>
#include <comutil.h>
#include <tchar.h>
#include <mbstring.h>

void dumpBin(LPCSTR type, LPCSTR data, size_t len) {
	printf("%s (address=0x%08x): \n", type, (unsigned int)data);
	for (size_t idx = 0; len > idx; idx++) {
		printf("\t");
		for (size_t cnt = 0; (len > idx) && (16 > cnt); cnt++, idx++) {
			printf("%02x ", (unsigned char)data[idx] );
		}
		printf("\n");
	}
}

// WideCharからMultiByteに変換
//関数内で領域を確保するので、使用後は開放すること
int convertWideToMulti(const wchar_t *pwsData, UINT encoding, LPSTR *pstrRslt)
{
	size_t len = wcslen(pwsData);
	int iW2MLen1 = WideCharToMultiByte(encoding, 0, pwsData, len, NULL, 0, NULL, NULL);
	if (iW2MLen1 == 0) {
		// 失敗
		return -1;
	}
	*pstrRslt = (LPSTR)malloc(iW2MLen1 + 1);
	if (*pstrRslt == NULL) {
		// 失敗
		return -1;
	}
	ZeroMemory(*pstrRslt, iW2MLen1 + 1);
	int iW2MLen2 = WideCharToMultiByte(encoding, 0, pwsData, len, (LPSTR)*pstrRslt, iW2MLen1, NULL, NULL);
	if (iW2MLen2 == 0) {
		// 失敗
		free(*pstrRslt);
		return -1;
	}
	return iW2MLen2;
}

// MultiByteからWideCharに変換
//関数内で領域を確保するので、使用後は開放すること
int convertMultiToWide(LPCSTR pcstrData, UINT encoding, LPWSTR *ppwsRslt )
{
	size_t len = strlen(pcstrData);
	int iW2MLen1 = MultiByteToWideChar(encoding, 0, pcstrData, len, NULL, 0);
	if (iW2MLen1 == 0) {
		// 失敗
		return -1;
	}
	*ppwsRslt = (LPWSTR)malloc((iW2MLen1 + 1)*2);
	if (*ppwsRslt == NULL) {
		// 失敗
		return -1;
	}
	ZeroMemory(*ppwsRslt, (iW2MLen1 + 1) * 2);
	int iW2MLen2 = MultiByteToWideChar(encoding, 0, pcstrData, len, (LPWSTR)*ppwsRslt, iW2MLen1);
	if (iW2MLen2 == 0) {
		// 失敗
		free(*ppwsRslt);
		return -1;
	}
	return iW2MLen2 * 2;
}

int main()
{
	const wchar_t *pwsData =
		L"kotatuinu!\n"
		L"炬燵犬!\n"
		L"コタツイヌ\n";

	printf("データ:%ls\n", pwsData);

	// wchar_t
	size_t len = wcslen(pwsData);
	dumpBin("wchar_t", (LPCSTR)pwsData, len*2);

	// _bstr_t -> BSTR
	_bstr_t bstrData1(pwsData);
	BSTR bsData1 = bstrData1;
	len = SysStringByteLen(bsData1);
	dumpBin("_bstr_t -> BSTR", (LPCSTR)bsData1, len);

	// _bstr_t.copy(false) -> BSTR
	// _bstr_t.copy(false)は_bstr_tのm_wstrメンバの領域を渡す→解放しちゃダメ
	BSTR bsData3 = bstrData1.copy(false);
	len = SysStringByteLen(bsData3);
	dumpBin("_bstr_t.copy(false) -> BSTR", (LPCSTR)bsData3, len);

	// _bstr_t.copy(true) -> BSTR
	// _bstr_t.copy(true)は新たに領域を取得する→SysFreeString()で解放が必要
	BSTR bsData2 = bstrData1.copy(true);
	len = SysStringByteLen(bsData2);
	dumpBin("_bstr_t.copy(true) -> BSTR", (LPCSTR)bsData2, len);
	::SysFreeString(bsData2);

	// _bstr_t -> const char *
	const char *szData1 = (const char*)bstrData1;
	len = strlen(szData1);
	dumpBin("_bstr_t -> const char *", (LPCSTR)szData1, len);

	// wchar->multibyte(encode UTF8)
	LPSTR pszData4;
	int iRtn = convertWideToMulti(pwsData, CP_UTF8, &pszData4);
	len = strlen(pszData4);
	len = _mbstrlen(pszData4);
	dumpBin("wchar->multibyte(encode UTF8)", (LPCSTR)pszData4, len);
	//free(pszData4);

	// wchar->multibyte(encode SHIFT-JIS)
	LPSTR pszData5;
	iRtn = convertWideToMulti(pwsData, CP_ACP, &pszData5);
	len = strlen(pszData5);
	len = _mbstrlen(pszData5);
	dumpBin("wchar->multibyte(encode SHIFT-JIS)", (LPCSTR)pszData5, len);
	free(pszData5);

	// multibyte(UTF-8)->wchar(UNICODE)->multibyte(SHIFT-JIS)
	LPWSTR pwsData1;
	LPSTR pszData6;
	iRtn = convertMultiToWide((LPCSTR)pszData4, CP_UTF8, &pwsData1);
	iRtn = convertWideToMulti(pwsData1, CP_ACP, &pszData6);
	dumpBin("multibyte(UTF-8)->wchar(UNICODE)->multibyte(SHIFT-JIS)", (LPCSTR)pszData6, iRtn);
	free(pszData4);
	free(pszData6);
	free(pwsData1);

	return 0;
}

出力結果

データ:kotatuinu!
wchar_t (address=0x00f5cc5c):
        6b 00 6f 00 74 00 61 00 74 00 75 00 69 00 6e 00
        00 21 00 0a 00 ac 70 f5 71 ac 72 01 ff 0a 00 7a
        80 ff 82 ff 72 ff 87 ff 0a 00
_bstr_t -> BSTR (address=0x00d96da4):
        6b 00 6f 00 74 00 61 00 74 00 75 00 69 00 6e 00
        00 21 00 0a 00 ac 70 f5 71 ac 72 01 ff 0a 00 7a
        80 ff 82 ff 72 ff 87 ff 0a 00
_bstr_t.copy(false) -> BSTR (address=0x00d96da4):
        6b 00 6f 00 74 00 61 00 74 00 75 00 69 00 6e 00
        00 21 00 0a 00 ac 70 f5 71 ac 72 01 ff 0a 00 7a
        80 ff 82 ff 72 ff 87 ff 0a 00
_bstr_t.copy(true) -> BSTR (address=0x00d96a44):
        6b 00 6f 00 74 00 61 00 74 00 75 00 69 00 6e 00
        00 21 00 0a 00 ac 70 f5 71 ac 72 01 ff 0a 00 7a
        80 ff 82 ff 72 ff 87 ff 0a 00
_bstr_t -> const char * (address=0x00d96ee0):
        6b 6f 74 61 74 75 69 6e 75 21 0a e0 78 e0 9d 8c
        81 49 0a ba c0 c2 b2 c7 0a
wchar->multibyte(encode UTF8) (address=0x00d8b6c0):
        6b 6f 74 61 74 75 69 6e 75 21 0a e7 82 ac e7 87
        e7 8a ac ef bc 81 0a ef bd ba ef be 80 ef be 82
        bd b2 ef be 87 0a
wchar->multibyte(encode SHIFT-JIS) (address=0x00d96d30):
        6b 6f 74 61 74 75 69 6e 75 21 0a e0 78 e0 9d 8c
        81 49 0a ba c0 c2 b2 c7 0a
multibyte(UTF-8)->wchar(UNICODE)->multibyte(SHIFT-JIS) (address=0x00d96fb8):
        6b 6f 74 61 74 75 69 6e 75 21 0a e0 78 e0 9d 8c
        81 49 0a ba c0 c2 b2 c7 0a

2017年5月24日 (水)

about:blankはインターネットゾーン!?

#2017/5/25修正(マイコンピュータゾーンを追記)

先日「プログラムから(ファイルを使わないで)IEを起動しXMLを開く方法」で開いたページプロパティのゾーンが”インターネット|保護モード:有効”となっていた。なんでインターネット?
ローカルファイルを開いた時には、”マイコンピュータ|保護モード:有効”となるのに。

ゾーンの違いにより何が異なるかというと、ローカルファイルではJavaScriptの実行に「ブロックされているコンテンツを許可」ボタンを押さなければいけないが、インターネットゾーンではそれが無くてもJavascriptは動くという動作の違いが出てくる。(ただしインターネットオプション-セキュリティの設定による)

Internet Explorerにはセキュリティゾーンというものがあり、インターネットオプション セキュリティで以下の4種類の設定ができる。
また、インターネットオプションには表示されていないが+1種類が隠しである。(レジストリの設定により表示できる)

  • インターネットゾーン
  • ローカル イントラネットゾーン
  • 信頼済みサイト ゾーン
  • 制限付きサイトゾーン
  • マイコンピュータゾーン

ローカルのファイルは、マイコンピュータゾーンに該当する。
ちなみに、インターネットオプション セキュリティにマイコンピュータゾーンを表示させるには、以下のレジストリを設定すればよい。
 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0
 項目:Flags の値を0x21から0x47にする、

インターネットゾーンは、ローカル イントラネットゾーン・信頼済みサイトゾーン・制限付きサイトゾーンのどれにも当てはまらないときに該当する。

信頼済みサイトゾーン・制限付きサイトゾーンは、明示的にURLを登録する必要があるので、通常の環境では当てはまらない。
ローカル イントラネットゾーンは、以下の3つの選択オプション+URLの登録で指定できる。

  • 他のゾーンに指定されていないローカル(イントラネット)のサイトを全て含める
  • プロキシサーバを使用しないサイトを全て含める(接続-LANの設定-プロキシサーバ接続で設定)
  • 全てのネットワークパス(UNC)を含める

"about:blank"は、ローカル イントラネットではないので(他のゾーンに設定されていないし)、結局、インターネットゾーンと判定されてしまう。
→参考:Microsoft TechNet「IE のセキュリティ ゾーンについて」

なお、"about:blank"は、空白ページを示すもので以下のレジストリにURLが登録されている。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\AboutURLs の blank項目。登録されている文字列値は"res://mshtml.dll/blank.htm"

about:blankを入力すると、res://mshtml.dll/blank.htmのページが表示される。
直接、URLに”res://mshtml.dll/blank.htm”を入れてIEで表示させると、ローカル イントラネットゾーンになる。仕事場のPCだとローカル イントラネットゾーンだったけど、家ではインターネットゾーンになった。(ちなみに上記レジストリキーを見ると他にもabout:系があることがわかる。)
about:blankをローカル イントラネットゾーンと判定されるためには、インターネットオプション-セキュリティ-ローカル イントラネットのサイトに追加するしかないようだ。でも、そんなことしてもちっともうれしくないか・・・。

インターネットオプション-セキュリティ-ローカル イントラネットのサイトは、以下のレジストリに登録されるので、無理やり通そうと思えばできなくはない・・・。HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains

→参考:MSDN「上級ユーザー向けの Internet Explorer セキュリティ ゾーン関連のレジストリ エントリ」

なお、ローカル イントラネットゾーンのページは「保護モード:無効」となっており、通常、インターネットゾーンのリンクを開くと「保護モード:有効」となるが、VC++ のデバック実行で開いたページからインターネットゾーンのリンクを開いても「保護モード:無効」のままになる。

保護モードが有効であると、IE上で動作するプロセスやアドオンがシステムへのアクセス権限などに制約される。つまり、保護モード:無効のままではヤバい。
(VC++のデバッグ実行ではなく)デバックオプションで生成したexeでも、exeファイルをキックして起動すれば上記の現象は起きないので、通常は問題にならないけど。テストで実行していたら、振る舞いが違うので悩んだので、ここに記しておく。

セキュリティ周りはとてもめんどくさく、環境・設定によって結果が変わってきて安定した結果を得られにくいので混乱してくる。
文句言われたくないので触りたくないな。

2017年5月20日 (土)

プログラムから(ファイルを使わないで)IEを起動しXMLを開く方法

お仕事で、WindowsアプリからIEを開くときに一時ファイルを使わない方法はないかということで調査してみた。

  • IEはCOMを使えば起動・終了や、データの表示などコントロールできる。
    IEの起動・終了、ステースバーなどのUIに関する表示・非表示はShDocVW.dllを使う。
    HTMLをIEに投入するには、HTML・CSSなど解析・表示を行うMSHTML.dllを使う。
    詳細は、MSDN「Internet ExplorerIEのアーキテクチャ」
  • 上記のMSHTMLは、HTMLのみ受け付ける。プログラムからXML+XSLのXMLをIEに渡してもxml-stylesheetに書かれたXSLを読み込まない。しかし、普通にIEからXMLファイルを読み込んでみると、XSLも読み込んでくれて期待した通りに表示される。これは悩んだ。
    →MSXMLのtransformNode()を使ってXMLにXSLを反映させることで、HTMLを生成できる。

超絶参考になったサイト:VC++ WebBrowser COMメモ(Hishidama's VC++ WebBrowser-control Memo)

データはOPEN DESIGN BOOKS「XML+XSLT実用スーパーサンプル集」から持ってきた。XML→XSL→XSLという形で、XSLからXSLファイルを参照しているもの。こういう形では、XMLから参照しているXSLを読み込ませればいい。XSLから参照しているXSLは読み込む必要が無い。
これとてもいい本です。しかし、絶版なのね。


以下のプログラムはWin32コンソールに貼り付ければOK。XMLは貼り付けてあるけど、XSLファイルは自前で用意する必要がある。
上記の本を何とか手に入れてくれたまえ。

// IETest1.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

#import <msxml3.dll>
#import <shdocvw.dll>
#import <mshtml.tlb>

wchar_t *test2 =
_T("<?xml version=\"1.0\" encoding=\"Shift_JIS\"?>")
_T("<?xml-stylesheet type=\"text/xsl\" href=\"C:\\temp\\apply-imports1.xsl\"?>")
_T("<全体>")
_T("<情報>")
_T("<氏名>愛媛花子</氏名>")
_T("<ハンドル>hanako</ハンドル>")
_T("<住所>松山市道後1-1-1</住所>")
_T("<勤務先>道後IT株式会社</勤務先>")
_T("</情報>")
_T("<情報>")
_T("<氏名>夏目団吾</氏名>")
_T("<ハンドル>dango</ハンドル>")
_T("<住所>松山市湯渡2-2-2</住所>")
_T("<勤務先>松山XMLセンター</勤務先>")
_T("</情報>")
_T("<情報>")
_T("<氏名>九里杏子</氏名>")
_T("<ハンドル>あんこ</ハンドル>")
_T("<住所>松山市文京町3-3-3</住所>")
_T("<勤務先>伊予XSL株式会社</勤務先>")
_T("</情報>")
_T("</全体>");

bool convertXMLandXSLtoHTML(_bstr_t xml, const variant_t xslFileName, _bstr_t *html) 
{
	bool bRslt = true;
	MSXML2::IXMLDOMDocument2Ptr pXMLDoc = NULL;
	MSXML2::IXMLDOMDocument2Ptr pXSLDoc = NULL;

	HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXMLDoc);
	if (FAILED(hr)) {
		bRslt = false;
		goto FUNC_END;
	}
	hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXSLDoc);
	if (FAILED(hr)) {
		bRslt = false;
		goto FUNC_END;
	}

	pXMLDoc->validateOnParse = TRUE;
	pXSLDoc->validateOnParse = TRUE;

	//pXMLDoc->load(xml);	// XMLファイル読込
	pXMLDoc->loadXML(_bstr_t(test2));	// XMLデータ設定

	// XSLファイル読込(こちらも文字列で設定できるけど)
	pXSLDoc->load(xslFileName);

	try{
		// XML + XSL → HTMLデータ生成
		*html = pXMLDoc->transformNode(pXSLDoc);
	}
	catch (_com_error e) {
		bRslt = false;
		throw e;
	}

FUNC_END:
	pXMLDoc = NULL;
	pXSLDoc = NULL;

	return bRslt;
}

bool writeHtml(SHDocVw::IWebBrowser2Ptr &pIE, LPCTSTR html)
{
	bool ret = false;
	_bstr_t bstr = html;

	MSHTML::IHTMLDocument2Ptr pDoc(pIE->Document);
	if (pDoc == nullptr) {
		goto FUNC_END;
	}

	SAFEARRAY* sfArray = ::SafeArrayCreateVector(VT_VARIANT, 0, 1);
	VARIANT* var;
	HRESULT hr = ::SafeArrayAccessData(sfArray, reinterpret_cast<void**>(&var));
	if (FAILED(hr)) {
		goto FUNC_END;
	}

	V_VT(var) = VT_BSTR;
	V_BSTR(var) = bstr;

	hr = ::SafeArrayUnaccessData(sfArray);
	if (FAILED(hr)) {
		goto FUNC_END;
	}

	hr = pDoc->write(sfArray);
	if (FAILED(hr)) {
		goto FUNC_END;
	}

	hr = pDoc->close();
	if (FAILED(hr)) {
		goto FUNC_END;
	}

	ret = true;

FUNC_END:
	pDoc = NULL;
	::SafeArrayDestroy(sfArray);

	return ret;
}

// IEを起動してhtmlデータを書き込む
// IEをコントロールしたい(IEを閉じるなど)場合は、WebBrowserのインスタンスを外に出して管理した方がよい
void openIE(const BSTR html)
{
	SHDocVw::IWebBrowser2Ptr pIE;

	// IE 起動+HTMLデータ設定+表示
	HRESULT hr = pIE.CreateInstance(__uuidof(SHDocVw::InternetExplorer));
	if (FAILED(hr)) {
		return;
	}

	pIE->Navigate(L"about:blank");	//何か設定しないでHTMLを書き込むと例外が発生する。空文字を入れると"http:///"となる
	bool bRslt = writeHtml(pIE, html);
	if (!bRslt)
	{
		return;
	}
	pIE->MenuBar = VARIANT_FALSE;
	pIE->ToolBar = VARIANT_FALSE;
	pIE->StatusBar = VARIANT_TRUE;
	pIE->Visible = VARIANT_TRUE;	// IEを表示状態にする。ここで見えるようになる。

	pIE = NULL;
}

int main(int argc, char* argv[])
{
	int rtn = -1;
	_bstr_t html;

	_bstr_t xml = _bstr_t(_T("C:\\temp\\apply-imports.xml"));
	variant_t xslFileName = _bstr_t(_T("c:\\temp\\apply-imports1.xsl"));

	HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);

	try {
		bool bRslt = convertXMLandXSLtoHTML(xml, xslFileName, &html);
		if (!bRslt) {
			goto FUNC_END;
		}
	}
	catch (_com_error e) {
		fprintf(stderr, "COM ERROR!\n");
		fprintf(stderr, " Error = 0x%08lx\n", e.Error());
		fprintf(stderr, " ErrorMessage = %s\n", (LPCSTR)_bstr_t(e.ErrorMessage()));
		fprintf(stderr, " Description = %s\n", (LPCSTR)_bstr_t(e.Description()));
		fprintf(stderr, " Source = %s\n", (LPCSTR)_bstr_t(e.Source()));
	}

	if (html.length() == 0) {
		goto FUNC_END;
	}

	openIE(html);
	rtn = 0;

FUNC_END:
	::CoUninitialize();

	return rtn;

}

●2017/7/22 追記
IEに書き込むときSAFEARRYにBSTR型でデータを入れている。
BSTR型は、UNICODE(内部ではUTF-16)なので、結果、IEに渡せるデータはUTF-16となる。IEのエンコードもUNICODEとなっている。
このことが何の影響がでるかというと、FORMのPOSTデータがUNICODEしか渡せないということ。実際、SJISで試してみてWireSharkでPOSTデータを見るとUTF-8になっていた。IEなのでFORMタグにaccept-charsetが効かない。METAのcharsetを変えてもダメっぽい。
詳しい方法は割愛するが、javascriptでSJISのコードをinputタグのvalue属性に設定してみたけど(String.fromCharCodeでSJISのコードを変換してみたり、数値文字参照から文字列を設定してみたり)全然だめだった。UTF-8になってしまう。
オイラはWebサーバ構築の経験があまり無いので、UTF-8を受け付けないサーバはあるかしらんが、この機能を使って実装するには気を付ける必要がある。

XMLHttpRequestを使えばSJISをPOSTで渡すことができるけど、そのままだとResponseを受けてもデータとして受け取ってしまってブラウザで表示できないんだよね・・・。そこもjavascriptで表示する?URLがabout:blankになってしまうのはいまいちだと思うのだが。

2017年5月 4日 (木)

PowerShellでXPathを使う

PowerShellでXPathを使ってみる。
食わせるXPath式とXMLは、MSDN「XPath の例」と「XPath 構文のサンプル XML ファイル (inventory.xml)」に手を加えたもの。

上記のXPath式は、その前提となる位置までNodeを抽出しなくてはいけない。また、すべてのXPath式に該当する値が入っていないので、該当するタグ・属性・値を追加した。

●PowerShellプログラム

$xmlDoc = [xml](get-content ./inventory.xml -encoding utf8)
$xmlNameSpaceManager = new-object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
$xmlNameSpaceManager.AddNamespace("my","uri:mynamespace")

$formula=@()
get-content xpathSample.txt -encoding utf8 | % {
	if($formula.length -eq 0) {
		$formula = $_.split("`t")
		if($formula.length -eq 0) {
			$formula = @($_)
		}
	} else {
		write-output( "■{0} :`"{1}`"" -f ($formula -join " → "), $_ )
		$x = @($xmlDoc)
		$formula | % { 
			if($x -ne $null){
				$f = $_
				$tmp = @()
				$x | %{ $_.selectnodes($f, $xmlNameSpaceManager) } | % {
					if($_ -is [System.Xml.XmlNodeList]) {
						$_ | %{ $tmp += $_ }
					} else {
						$tmp += $_
					}
				}
				$x = $tmp
			} else {
				write-output("result : null")
				$x = $null
			}
		}

		$x | % {
			if($_.innerXML -ne $null) { write-output( "innerXML={0}" -f $_.innerXML ) }
			if($_.value -ne $null ) { write-output( "value={0}" -f $_.value) }
		}
		$formula = @()
	}
}

●XMLデータ:inventory.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="myfile.xsl" ?>
<bookstore specialty="novel">
  <book style="autobiography">
    <author>
      <first-name>Joe</first-name>
      <last-name>Bob</last-name>
      <award>Trenton Literary Review Honorable Mention</award>
    </author>
    <price>12</price>
  </book>
  <book style="textbook">
    <author>
      <first-name>Mary</first-name>
      <last-name>Boby</last-name>
      <publication>Selected Short Stories of
        <first-name>Mary</first-name>
        <last-name>Bob</last-name>
      </publication>
    </author>
    <editor>
      <first-name>Britney</first-name>
      <last-name>Bob</last-name>
    </editor>
    <price>55</price>
  </book>
  <magazine style="glossy" frequency="monthly">
    <price>2.50</price>
    <subscription price="24" per="year"/>
  </magazine>
  <book style="novel" id="myfave">
    <author>
      <first-name>Toni</first-name>
      <last-name>Bob</last-name>
      <degree from="Trenton U">B.A.</degree>
      <degree from="Harvard">Ph.D.</degree>
      <award>Pulitzer</award>
      <publication>Still in Trenton</publication>
      <publication>Trenton Forever</publication>
    </author>
    <price intl="Canada" exchange="0.7">6.50</price>
    <excerpt>
      <p>It was a dark and stormy night.</p>
      <p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p>
      <definition-list>
        <term>Trenton</term>
        <definition>misery</definition>
      </definition-list>
    </excerpt>
    <title>Toni Bob's novel</title>
  </book>
  <my:book xmlns:my="uri:mynamespace" style="leather" price="29.50">
    <my:title>Who's Who in Trenton</my:title>
    <my:author>Robert Bob</my:author>
  </my:book>
  <book style="test1">
    <author>Matthew Bob</author>
    <p>testMatthewBob</p>
  </book>
  <book style="test2">
    <author>
      <first-name>Bob</first-name>
      <p>testBob</p>
    </author>
  </book>
  <book style="test3">
    <title>test3_title</title>
    <author>
      <first-name>Bob</first-name>
      <p>testBob</p>
    </author>
  </book>
  <book style="test4">
    <title>test4_title</title>
    <author>
      <first.name>BobTest4</first.name>
      <p>test4Bob</p>
    </author>
  </book>
  <book style="test5">
    <title>test5_title</title>
    <author>
      <first-name>BobTest5.1</first-name>
    </author>
    <author>
      <first-name>BobTest5.2</first-name>
    </author>
    <author>
      <first-name>BobTest5.3</first-name>
    </author>
    <author>
      <first-name>BobTest5.4</first-name>
    </author>
  </book>
  <book style="test6" id="myfave">
    <author>
      <first-name>Toni</first-name>
      <last-name>Bob</last-name>
      <degree from="Trenton U">B.A.</degree>
      <degree from="Harvard">Ph.D.</degree>
      <award>Pulitzer</award>
    </author>
  </book>
  <book style="test7">
    <author>
      <first-name>Joe</first-name>
      <last-name>Bob</last-name>
    </author>
    <price>55</price>
  </book>
</bookstore>

●XPath式:xpathSample.txt

/bookstore/book	./author
現在のコンテキスト内のすべての <author> 要素。 これは、次の行の式に等しくなることに注意してください。
/bookstore/book	author
現在のコンテキスト内のすべての <author> 要素。
/bookstore/book/author	first.name
現在のコンテキスト内のすべての <first.name> 要素。
/bookstore
このドキュメントのドキュメント要素 (<bookstore>)。
//author
このドキュメント内のすべての <author> 要素。
/bookstore	book[/bookstore/@specialty=@style]
ドキュメントのルートにある <bookstore> 要素の specialty 属性と同じ値の style 属性を持っているすべての <book> 要素。
/bookstore/book	author/first-name
<author> 要素の子要素であるすべての <first-name> 要素。
bookstore//title
<bookstore> 要素内の 1 段階以上深いレベル (任意の子孫) に含まれているすべての <title> 要素。 これは、次の行の式とは異なる点に注意してください。
bookstore/*/title
<bookstore> 要素の孫であるすべての <title> 要素。
bookstore//book/excerpt//emph
<bookstore> 要素内の任意の場所にある <book> 要素の子要素 <excerpt> 内の任意の場所にあるすべての <emph> 要素。
.//title
現在のコンテキストから 1 レベル以上の深さにあるすべての <title> 要素。 この状況は、ピリオド表記が必須である場合において、基本的に 1 回だけ発生することに注意してください。
/bookstore/book	author/*
<author> 要素の子要素であるすべての要素。
/bookstore	book/*/last-name
<book> 要素の孫であるすべての <last-name> 要素。
*/*
現在のコンテキストのすべての孫要素です。
*[@specialty]
specialty 属性を持つすべての要素。
/bookstore/book	@style
現在のコンテキストの style 属性。
/bookstore/book	price/@exchange
現在のコンテキスト内の <price> 要素の exchange 属性。
/bookstore/book	price/@exchange/total
属性には要素の子が含まれないため、空のノード セットが返ります。 この式は、XPath (XML Path Language) の文法上は使用可能ですが、厳密にいえば有効ではありません。
/bookstore	book[@style]
現在のコンテキストの style 属性を持つすべての <book> 要素。
/bookstore	book/@style
現在のコンテキストのすべての <book> 要素の style 属性。
/bookstore	@*
現在の要素のコンテキストのすべての属性。
/bookstore/book/author	./first-name
現在のコンテキスト ノード内のすべての <first-name> 要素。 これは、次の行の式に等しくなることに注意してください。
/bookstore/book/author	first-name
現在のコンテキスト ノード内のすべての <first-name> 要素。
/bookstore/book	author[1]
現在のコンテキスト ノード内の最初の <author> 要素。
/bookstore/book	author[first-name][3]
子要素 <first-name> を持っている 3 番目の <author> 要素。
/bookstore	my:book
my 名前空間の <book> 要素。
/bookstore	my:*
my 名前空間のすべての要素。
/bookstore	@my:*
my 名前空間からのすべての要素 (これには、my 名前空間からの要素の修飾されていない属性は含まれません)。
/bookstore	book[last()]
現在のコンテキスト ノードの最後の <book> 要素。
/bookstore	book/author[last()]
現在のコンテキスト ノードの個々の <book> 要素の最後の子要素 <author>。
/bookstore	(book/author)[last()]
現在のコンテキスト ノードの <book> 要素の子要素 <author> の集合全体で最後の <author> 要素。
/bookstore	book[excerpt]
少なくとも 1 つの子要素 <excerpt> を含むすべての <book> 要素。
/bookstore	book[excerpt]/title
少なくとも 1 つの子要素 <excerpt> を含む <book> 要素を親要素とするすべての <title> 要素。
/bookstore	book[excerpt]/author[degree]
少なくとも 1 つの子要素 <excerpt> を含む <book> 要素の子要素であると同時に、自身が少なくとも 1 つの子要素 <degree> を持っているすべての <author> 要素。
/bookstore	book[author/degree]
少なくとも 1 つの子要素 <degree> が含まれた <author> を子要素として持つすべての <book> 要素。
/bookstore/book	author[degree][award]
少なくとも 1 つの子要素 <degree> を含み、少なくとも 1 つの子要素 <award> を含む、すべての <author> 要素。
/bookstore/book	author[degree and award]
少なくとも 1 つの子要素 <degree> を含み、少なくとも 1 つの子要素 <award> を含む、すべての <author> 要素。
/bookstore/book	author[(degree or award) and publication]
少なくとも 1 つの <degree> または <award> を含み、少なくとも 1 つの <publication> を子要素として含むすべての <author> 要素。
/bookstore/book	author[degree and not(publication)]
少なくとも 1 つの子要素 <degree> を含んでいるが、子要素 <publication> を含んでいないすべての <author> 要素。
/bookstore/book	author[not(degree or award) and publication]
少なくとも 1 つの子要素 <publication> を含んでいるが、子要素 <degree> も子要素 <award> も含んでいないすべての <author> 要素。
/bookstore/book	author[last-name = "Bob"]
値が Bob である子要素 <last-name> を少なくとも 1 つ含むすべての <author> 要素。
/bookstore/book	author[last-name[1] = "Bob"]
最初の子要素 <last-name> の値が Bob になっているすべての <author> 要素。 これは、次の行の式に等しくなることに注意してください。
/bookstore/book	author[last-name [position()=1]= "Bob"]
最初の子要素 <last-name> の値が Bob になっているすべての <author> 要素。
/bookstore/book/author	degree[@from != "Harvard"]
from 属性が "Harvard" と等しくないすべての <degree> 要素。
/bookstore/book	author[. = "Matthew Bob"]
値が Matthew Bob になっているすべての <author> 要素。
/bookstore/book	author[last-name = "Bob" and ../price > 50]
値が Bob である子要素 <last-name> と、値が 50 を上回る兄弟要素 <price> を持っているすべての <author> 要素。
/bookstore	book[position() <= 3]
最初の 3 冊の本 (1、2、3)。
/bookstore/book	author[not(last-name = "Bob")]
値が Bob である子要素 <last-name> を持っていないすべての <author> 要素。
/bookstore/book	author[first-name = "Bob"]
値が Bob である子要素 <first-name> を 1 つ以上持っているすべての <author> 要素。
/bookstore/book	author[* = "Bob"]
値が Bob である任意の子要素を持っているすべての author 要素。
/bookstore/book	author[last-name = "Bob" and first-name = "Joe"]
値が Bob である子要素 <last-name> と、値が Joe である子要素 <first-name> を持っているすべての <author> 要素。
/bookstore/book	price[@intl = "Canada"]
持っている intl 属性が "Canada" と等しい、コンテキスト ノード内のすべての <price> 要素。
/bookstore/book/author	degree[position() < 3]
コンテキスト ノードの子要素である最初の 2 つの <degree> 要素。
/bookstore/book/excerpt	p/text()[2]
コンテキスト ノード内の個々の <p> 要素内の 2 番目のテキスト ノード。
/bookstore/book/author	ancestor::book[1]
コンテキスト ノードの最も近い祖先に当たる <book>。
/bookstore/book/author	ancestor::book[author][1]
コンテキスト ノードの最も近い祖先に当たる <book> であり、<author> 要素を子要素として持つ <book> 要素。
/bookstore/book/author/first-name	ancestor::author[parent::book][1]
現在のコンテキストで最も近い祖先に当たる <author> であり、<book> 要素を親として持つ <author> 要素。

●出力結果

■/bookstore/book → ./author :"現在のコンテキスト内のすべての <author> 要素。 これは、次の行の式に等しくなることに注意してください。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=Matthew Bob
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first.name>BobTest4</first.name><p>test4Bob</p>
innerXML=<first-name>BobTest5.1</first-name>
innerXML=<first-name>BobTest5.2</first-name>
innerXML=<first-name>BobTest5.3</first-name>
innerXML=<first-name>BobTest5.4</first-name>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore/book → author :"現在のコンテキスト内のすべての <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=Matthew Bob
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first.name>BobTest4</first.name><p>test4Bob</p>
innerXML=<first-name>BobTest5.1</first-name>
innerXML=<first-name>BobTest5.2</first-name>
innerXML=<first-name>BobTest5.3</first-name>
innerXML=<first-name>BobTest5.4</first-name>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore/book/author → first.name :"現在のコンテキスト内のすべての <first.name> 要素。"
innerXML=BobTest4
■/bookstore :"このドキュメントのドキュメント要素 (<bookstore>)。"
innerXML=<book style="autobiography"><author><first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award></author><price>12</price></book><book style="textbook"><author><first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication></author><editor><first-name>Britney</first-name><last-name>Bob</last-name></editor><price>55</price></book><magazine style="glossy" frequency="monthly"><price>2.50</price><subscription price="24" per="year" /></magazine><book style="novel" id="myfave"><author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title></book><my:book xmlns:my="uri:mynamespace" style="leather" price="29.50"><my:title>Who's Who in Trenton</my:title><my:author>Robert Bob</my:author></my:book><book style="test1"><author>Matthew Bob</author><p>testMatthewBob</p></book><book style="test2"><author><first-name>Bob</first-name><p>testBob</p></author></book><book style="test3"><title>test3_title</title><author><first-name>Bob</first-name><p>testBob</p></author></book><book style="test4"><title>test4_title</title><author><first.name>BobTest4</first.name><p>test4Bob</p></author></book><book style="test5"><title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author></book><book style="test6" id="myfave"><author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award></author></book><book style="test7"><author><first-name>Joe</first-name><last-name>Bob</last-name></author><price>55</price></book>
■//author :"このドキュメント内のすべての <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=Matthew Bob
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first.name>BobTest4</first.name><p>test4Bob</p>
innerXML=<first-name>BobTest5.1</first-name>
innerXML=<first-name>BobTest5.2</first-name>
innerXML=<first-name>BobTest5.3</first-name>
innerXML=<first-name>BobTest5.4</first-name>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■book[/bookstore/@specialty=@style] :"ドキュメントのルートにある <bookstore> 要素の specialty 属性と同じ値の style 属性を持っているすべての <book> 要素。"
■/bookstore/book → author/first-name :"<author> 要素の子要素であるすべての <first-name> 要素。"
innerXML=Joe
innerXML=Mary
innerXML=Toni
innerXML=Bob
innerXML=Bob
innerXML=BobTest5.1
innerXML=BobTest5.2
innerXML=BobTest5.3
innerXML=BobTest5.4
innerXML=Toni
innerXML=Joe
■bookstore//title :"<bookstore> 要素内の 1 段階以上深いレベル (任意の子孫) に含まれているすべての <title> 要素。 これは、次の行の式とは異なる点に注意してください。"
innerXML=Toni Bob's novel
innerXML=test3_title
innerXML=test4_title
innerXML=test5_title
■bookstore/*/title :"<bookstore> 要素の孫であるすべての <title> 要素。"
innerXML=Toni Bob's novel
innerXML=test3_title
innerXML=test4_title
innerXML=test5_title
■bookstore//book/excerpt//emph :"<bookstore> 要素内の任意の場所にある <book> 要素の子要素 <excerpt> 内の任意の場所にあるすべての <emph> 要素。"
innerXML=I
■.//title :"現在のコンテキストから 1 レベル以上の深さにあるすべての <title> 要素。 この状況は、ピリオド表記が必須である場合において、基本的に 1 回だけ発生することに注意してください。"
innerXML=Toni Bob's novel
innerXML=test3_title
innerXML=test4_title
innerXML=test5_title
■/bookstore/book → author/* :"<author> 要素の子要素であるすべての要素。"
innerXML=Joe
innerXML=Bob
innerXML=Trenton Literary Review Honorable Mention
innerXML=Mary
innerXML=Boby
innerXML=Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name>
innerXML=Toni
innerXML=Bob
innerXML=B.A.
innerXML=Ph.D.
innerXML=Pulitzer
innerXML=Still in Trenton
innerXML=Trenton Forever
innerXML=Bob
innerXML=testBob
innerXML=Bob
innerXML=testBob
innerXML=BobTest4
innerXML=test4Bob
innerXML=BobTest5.1
innerXML=BobTest5.2
innerXML=BobTest5.3
innerXML=BobTest5.4
innerXML=Toni
innerXML=Bob
innerXML=B.A.
innerXML=Ph.D.
innerXML=Pulitzer
innerXML=Joe
innerXML=Bob
■/bookstore → book/*/last-name :"<book> 要素の孫であるすべての <last-name> 要素。"
innerXML=Bob
innerXML=Boby
innerXML=Bob
innerXML=Bob
innerXML=Bob
innerXML=Bob
■*/* :"現在のコンテキストのすべての孫要素です。"
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award></author><price>12</price>
innerXML=<author><first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication></author><editor><first-name>Britney</first-name><last-name>Bob</last-name></editor><price>55</price>
innerXML=<price>2.50</price><subscription price="24" per="year" />
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title>
innerXML=<my:title xmlns:my="uri:mynamespace">Who's Who in Trenton</my:title><my:author xmlns:my="uri:mynamespace">Robert Bob</my:author>
innerXML=<author>Matthew Bob</author><p>testMatthewBob</p>
innerXML=<author><first-name>Bob</first-name><p>testBob</p></author>
innerXML=<title>test3_title</title><author><first-name>Bob</first-name><p>testBob</p></author>
innerXML=<title>test4_title</title><author><first.name>BobTest4</first.name><p>test4Bob</p></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award></author>
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name></author><price>55</price>
■*[@specialty] :"specialty 属性を持つすべての要素。"
innerXML=<book style="autobiography"><author><first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award></author><price>12</price></book><book style="textbook"><author><first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication></author><editor><first-name>Britney</first-name><last-name>Bob</last-name></editor><price>55</price></book><magazine style="glossy" frequency="monthly"><price>2.50</price><subscription price="24" per="year" /></magazine><book style="novel" id="myfave"><author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title></book><my:book xmlns:my="uri:mynamespace" style="leather" price="29.50"><my:title>Who's Who in Trenton</my:title><my:author>Robert Bob</my:author></my:book><book style="test1"><author>Matthew Bob</author><p>testMatthewBob</p></book><book style="test2"><author><first-name>Bob</first-name><p>testBob</p></author></book><book style="test3"><title>test3_title</title><author><first-name>Bob</first-name><p>testBob</p></author></book><book style="test4"><title>test4_title</title><author><first.name>BobTest4</first.name><p>test4Bob</p></author></book><book style="test5"><title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author></book><book style="test6" id="myfave"><author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award></author></book><book style="test7"><author><first-name>Joe</first-name><last-name>Bob</last-name></author><price>55</price></book>
■/bookstore/book → @style :"現在のコンテキストの style 属性。"
value=autobiography
value=textbook
value=novel
value=test1
value=test2
value=test3
value=test4
value=test5
value=test6
value=test7
■/bookstore/book → price/@exchange :"現在のコンテキスト内の <price> 要素の exchange 属性。"
value=0.7
■/bookstore/book → price/@exchange/total :"属性には要素の子が含まれないため、空のノード セットが返ります。 この式は、XPath (XML Path Language) の文法上は使用可能ですが、厳密にいえば有効ではありません。"
■/bookstore → book[@style] :"現在のコンテキストの style 属性を持つすべての <book> 要素。"
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award></author><price>12</price>
innerXML=<author><first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication></author><editor><first-name>Britney</first-name><last-name>Bob</last-name></editor><price>55</price>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title>
innerXML=<author>Matthew Bob</author><p>testMatthewBob</p>
innerXML=<author><first-name>Bob</first-name><p>testBob</p></author>
innerXML=<title>test3_title</title><author><first-name>Bob</first-name><p>testBob</p></author>
innerXML=<title>test4_title</title><author><first.name>BobTest4</first.name><p>test4Bob</p></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award></author>
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name></author><price>55</price>
■/bookstore → book/@style :"現在のコンテキストのすべての <book> 要素の style 属性。"
value=autobiography
value=textbook
value=novel
value=test1
value=test2
value=test3
value=test4
value=test5
value=test6
value=test7
■/bookstore → @* :"現在の要素のコンテキストのすべての属性。"
value=novel
■/bookstore/book/author → ./first-name :"現在のコンテキスト ノード内のすべての <first-name> 要素。 これは、次の行の式に等しくなることに注意してください。"
innerXML=Joe
innerXML=Mary
innerXML=Toni
innerXML=Bob
innerXML=Bob
innerXML=BobTest5.1
innerXML=BobTest5.2
innerXML=BobTest5.3
innerXML=BobTest5.4
innerXML=Toni
innerXML=Joe
■/bookstore/book/author → first-name :"現在のコンテキスト ノード内のすべての <first-name> 要素。"
innerXML=Joe
innerXML=Mary
innerXML=Toni
innerXML=Bob
innerXML=Bob
innerXML=BobTest5.1
innerXML=BobTest5.2
innerXML=BobTest5.3
innerXML=BobTest5.4
innerXML=Toni
innerXML=Joe
■/bookstore/book → author[1] :"現在のコンテキスト ノード内の最初の <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=Matthew Bob
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first.name>BobTest4</first.name><p>test4Bob</p>
innerXML=<first-name>BobTest5.1</first-name>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore/book → author[first-name][3] :"子要素 <first-name> を持っている 3 番目の <author> 要素。"
innerXML=<first-name>BobTest5.3</first-name>
■/bookstore → my:book :"my 名前空間の <book> 要素。"
innerXML=<my:title xmlns:my="uri:mynamespace">Who's Who in Trenton</my:title><my:author xmlns:my="uri:mynamespace">Robert Bob</my:author>
■/bookstore → my:* :"my 名前空間のすべての要素。"
innerXML=<my:title xmlns:my="uri:mynamespace">Who's Who in Trenton</my:title><my:author xmlns:my="uri:mynamespace">Robert Bob</my:author>
■/bookstore → @my:* :"my 名前空間からのすべての要素 (これには、my 名前空間からの要素の修飾されていない属性は含まれません)。"
■/bookstore → book[last()] :"現在のコンテキスト ノードの最後の <book> 要素。"
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name></author><price>55</price>
■/bookstore → book/author[last()] :"現在のコンテキスト ノードの個々の <book> 要素の最後の子要素 <author>。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=Matthew Bob
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first.name>BobTest4</first.name><p>test4Bob</p>
innerXML=<first-name>BobTest5.4</first-name>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore → (book/author)[last()] :"現在のコンテキスト ノードの <book> 要素の子要素 <author> の集合全体で最後の <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore → book[excerpt] :"少なくとも 1 つの子要素 <excerpt> を含むすべての <book> 要素。"
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title>
■/bookstore → book[excerpt]/title :"少なくとも 1 つの子要素 <excerpt> を含む <book> 要素を親要素とするすべての <title> 要素。"
innerXML=Toni Bob's novel
■/bookstore → book[excerpt]/author[degree] :"少なくとも 1 つの子要素 <excerpt> を含む <book> 要素の子要素であると同時に、自身が少なくとも 1 つの子要素 <degree> を持っているすべての <author> 要素。"
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
■/bookstore → book[author/degree] :"少なくとも 1 つの子要素 <degree> が含まれた <author> を子要素として持つすべての <book> 要素。"
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award></author>
■/bookstore/book → author[degree][award] :"少なくとも 1 つの子要素 <degree> を含み、少なくとも 1 つの子要素 <award> を含む、すべての <author> 要素。"
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
■/bookstore/book → author[degree and award] :"少なくとも 1 つの子要素 <degree> を含み、少なくとも 1 つの子要素 <award> を含む、すべての <author> 要素。"
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
■/bookstore/book → author[(degree or award) and publication] :"少なくとも 1 つの <degree> または <award> を含み、少なくとも 1 つの <publication> を子要素として含むすべての <author> 要素。"
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
■/bookstore/book → author[degree and not(publication)] :"少なくとも 1 つの子要素 <degree> を含んでいるが、子要素 <publication> を含んでいないすべての <author> 要素。"
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
■/bookstore/book → author[not(degree or award) and publication] :"少なくとも 1 つの子要素 <publication> を含んでいるが、子要素 <degree> も子要素 <award> も含んでいないすべての <author> 要素。"
innerXML=<first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication>
■/bookstore/book → author[last-name = "Bob"] :"値が Bob である子要素 <last-name> を少なくとも 1 つ含むすべての <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore/book → author[last-name[1] = "Bob"] :"最初の子要素 <last-name> の値が Bob になっているすべての <author> 要素。 これは、次の行の式に等しくなることに注意してください。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore/book → author[last-name [position()=1]= "Bob"] :"最初の子要素 <last-name> の値が Bob になっているすべての <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore/book/author → degree[@from != "Harvard"] :"from 属性が "Harvard" と等しくないすべての <degree> 要素。"
innerXML=B.A.
innerXML=B.A.
■/bookstore/book → author[. = "Matthew Bob"] :"値が Matthew Bob になっているすべての <author> 要素。"
innerXML=Matthew Bob
■/bookstore/book → author[last-name = "Bob" and ../price > 50] :"値が Bob である子要素 <last-name> と、値が 50 を上回る兄弟要素 <price> を持っているすべての <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore → book[position() <= 3] :"最初の 3 冊の本 (1、2、3)。"
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award></author><price>12</price>
innerXML=<author><first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication></author><editor><first-name>Britney</first-name><last-name>Bob</last-name></editor><price>55</price>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title>
■/bookstore/book → author[not(last-name = "Bob")] :"値が Bob である子要素 <last-name> を持っていないすべての <author> 要素。"
innerXML=<first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication>
innerXML=Matthew Bob
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first.name>BobTest4</first.name><p>test4Bob</p>
innerXML=<first-name>BobTest5.1</first-name>
innerXML=<first-name>BobTest5.2</first-name>
innerXML=<first-name>BobTest5.3</first-name>
innerXML=<first-name>BobTest5.4</first-name>
■/bookstore/book → author[first-name = "Bob"] :"値が Bob である子要素 <first-name> を 1 つ以上持っているすべての <author> 要素。"
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
■/bookstore/book → author[* = "Bob"] :"値が Bob である任意の子要素を持っているすべての author 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore/book → author[last-name = "Bob" and first-name = "Joe"] :"値が Bob である子要素 <last-name> と、値が Joe である子要素 <first-name> を持っているすべての <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>
■/bookstore/book → price[@intl = "Canada"] :"持っている intl 属性が "Canada" と等しい、コンテキスト ノード内のすべての <price> 要素。"
innerXML=6.50
■/bookstore/book/author → degree[position() < 3] :"コンテキスト ノードの子要素である最初の 2 つの <degree> 要素。"
innerXML=B.A.
innerXML=Ph.D.
innerXML=B.A.
innerXML=Ph.D.
■/bookstore/book/excerpt → p/text()[2] :"コンテキスト ノード内の個々の <p> 要素内の 2 番目のテキスト ノード。"
innerXML=
value= have.
■/bookstore/book/author → ancestor::book[1] :"コンテキスト ノードの最も近い祖先に当たる <book>。"
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award></author><price>12</price>
innerXML=<author><first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication></author><editor><first-name>Britney</first-name><last-name>Bob</last-name></editor><price>55</price>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title>
innerXML=<author>Matthew Bob</author><p>testMatthewBob</p>
innerXML=<author><first-name>Bob</first-name><p>testBob</p></author>
innerXML=<title>test3_title</title><author><first-name>Bob</first-name><p>testBob</p></author>
innerXML=<title>test4_title</title><author><first.name>BobTest4</first.name><p>test4Bob</p></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award></author>
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name></author><price>55</price>
■/bookstore/book/author → ancestor::book[author][1] :"コンテキスト ノードの最も近い祖先に当たる <book> であり、<author> 要素を子要素として持つ <book> 要素。"
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award></author><price>12</price>
innerXML=<author><first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication></author><editor><first-name>Britney</first-name><last-name>Bob</last-name></editor><price>55</price>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication></author><price intl="Canada" exchange="0.7">6.50</price><excerpt><p>It was a dark and stormy night.</p><p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p><definition-list><term>Trenton</term><definition>misery</definition></definition-list></excerpt><title>Toni Bob's novel</title>
innerXML=<author>Matthew Bob</author><p>testMatthewBob</p>
innerXML=<author><first-name>Bob</first-name><p>testBob</p></author>
innerXML=<title>test3_title</title><author><first-name>Bob</first-name><p>testBob</p></author>
innerXML=<title>test4_title</title><author><first.name>BobTest4</first.name><p>test4Bob</p></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<title>test5_title</title><author><first-name>BobTest5.1</first-name></author><author><first-name>BobTest5.2</first-name></author><author><first-name>BobTest5.3</first-name></author><author><first-name>BobTest5.4</first-name></author>
innerXML=<author><first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award></author>
innerXML=<author><first-name>Joe</first-name><last-name>Bob</last-name></author><price>55</price>
■/bookstore/book/author/first-name → ancestor::author[parent::book][1] :"現在のコンテキストで最も近い祖先に当たる <author> であり、<book> 要素を親として持つ <author> 要素。"
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name><award>Trenton Literary Review Honorable Mention</award>
innerXML=<first-name>Mary</first-name><last-name>Boby</last-name><publication>Selected Short Stories of
        <first-name>Mary</first-name><last-name>Bob</last-name></publication>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award><publication>Still in Trenton</publication><publication>Trenton Forever</publication>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>Bob</first-name><p>testBob</p>
innerXML=<first-name>BobTest5.1</first-name>
innerXML=<first-name>BobTest5.2</first-name>
innerXML=<first-name>BobTest5.3</first-name>
innerXML=<first-name>BobTest5.4</first-name>
innerXML=<first-name>Toni</first-name><last-name>Bob</last-name><degree from="Trenton U">B.A.</degree><degree from="Harvard">Ph.D.</degree><award>Pulitzer</award>
innerXML=<first-name>Joe</first-name><last-name>Bob</last-name>

2017年3月 6日 (月)

オイラ、dockerしてるぜ パーソナルファイアウォールの認証を通す

今の職場は、Windowsにパーソナルファイアウォールが設定されていて、検疫ができていないと外部と接続できない。
インターネットオプション - 接続 - LANの設定で、プロキシサーバにアドレス:127.0.0.1 ポート:8000 となっているとする。
そんな環境でDocker toolbox(Windows)で環境を作ろうとして、認証が通らず困っていた。

Docker toolboxは、VirtualBox上でLinuxが動いてこれがホストOSとなるわけだけど、Windowsに対して認証するにはどうすればいいか?

まず、LinuxでProxy認証を通すには、以下の環境変数を設定すればよい。

export http_proxy=http://<UserID>:<Password>@<Proxy IPAddress>:<PortNo>
export https_proxy=https://<UserID>:<Password>@<Proxy IPAddress>:<PortNo>

しかし、WindowsでインターネットオプションのLAN設定に登録されているプロキシのIPアドレス127.0.0.1では、DockerのホストOSになってしまう。
かといってWindowsのIPアドレスを設定すると、認証が通らない。(内部ではなく外部のIPアドレスになるのか?)

答えは、VirtualBoxから見たWindowsのIPアドレスを設定すればいい。
DockerホストOSから以下のように”ip r”を実行してeth0のIPアドレスを確認する。

docker@default:~$ ip r
default via 10.0.2.2 dev eth0  metric 1
10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15
127.0.0.1 dev lo  scope link
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1
192.168.99.0/24 dev eth1  proto kernel  scope link  src 192.168.99.100

上記のeth0のIPアドレス10.0.2.2をDockerホストOSの環境変数に反映させるのだけれど、具体的にどうすればよいか?

docker-docs-ja トラブルシューティング「Docker マシン上の /var/lib/boot2docker/profile を更新」に方法が書いてある。(今回の問題環境に合わせて、環境変数の定義を書き換えてあります。認証のユーザID,パスワードは UserID/Passwordで、パーソナルファイアウォールのポートは8000とする。)
これDocker Quickstart Terminalから起動したターミナルで実行する必要があり。

$ docker-machine ssh default
docker@default:~$ sudo vi /var/lib/boot2docker/profile

-以下の内容をprofile内に追記-
export "HTTP_PROXY=http://UserID:Password@10.0.2.2:8000"
export "HTTPS_PROXY=http://UserID:Password@10.0.2.2:8000" export "NO_PROXY=192.168.99.*,*.local,169.254/16,*.example.com,192.168.59.*"
-記入し終わったらviを抜けて以下のコマンドを実行- docker@default:~$ sudo /etc/init.d/docker restart docker@default:~$ exit

これでdocker pullが通るはず。
でも、立ち上げたdockerからapt-getが通らないんだよな・・・。

2017年1月24日 (火)

C#で並列実行

codeIQの問題を解いていたのだけれど、入力数値が大きくなるとループ数が多くなり、その結果、実行時間1秒以内の制限を超えてしまったので、CPUリソースでぶん殴る方法=並列実行で対応してみようとしたいきさつ。

最終的に自分のノートPCでは、0.04秒程度まで縮められたのだが、codeIQの実行環境では並列実行がまともに効かないようで、やっぱり1秒を超えてしまいクリアとならなかった。
クリアできなかったとはいえ試行錯誤で早くなったので、回答期限が切れた今、C#の並行実行について書いてみる。

  • C# 平行実行で検索すると大体、async と await というキーワードが出てくる。
    これはGUIでボタン押下の処理でレスポンスが掛かるとき(Webサーバからの応答待ちが入るとか)、画面が固まるのを防ぐためのものの意味合いが強い模様。xxxAsync()という並列実行向けを呼ぶことで並列実行というかGUIに処理を戻して、バックグラウンドでレスポンス待ちをする。
    今回の処理では使えない。
  • 今回の処理のように、ループ数が多くなってしまうので1000回毎に分割して並行実行するというような使い方で用いる方法としてTaskを使う。
    ↓以下抜粋。些かこのコードが正しいかわからないけれど、まあ、動いている。

class CodeIQSample
{

    static void Main()
    {
        String line;
        MatchCollection mc;
        long[] val = new long[2];

        for (; (line = Console.ReadLine()) != null;)
        {
            mc = Regex.Matches(line, @"\d+");
            // 引数は2つ以外はNG
            if (mc.Count != 2)
            {
                continue;
            }
            int index = 0;
            foreach (System.Text.RegularExpressions.Match m in mc)
            {
                val[index] = long.Parse(m.Value);
                index++;
            }
            //int result;
            long lower = val[0];
            long upper = val[1];

            // 入力値が2つとも同値はNG
            if (lower == upper)
            {
                continue;
            }
            if (lower > upper)
            {
                lower = val[1];
                upper = val[0];
            }

            FindSumRange fsr = new FindSumRange();
            fsr.upper = upper;
            fsr.lower = lower;

            Task<int> result = fsr.calc();

            result.Wait();             System.Console.Write("{0}\n", result.Result);         }     } } class FindSumRange {     public long upper { get; set; }     public long lower { get; set; }     private long compval_;     public async Task calc()     {         int resultCount = 0;         var tasks = new List<int>();         for (long rangeLower = lower; upper > rangeLower; rangeLower += 1000)         {             long rangeUpper = (rangeLower + 1000 > upper) ? upper : rangeLower + 1000;             var task = new task(lower, upper, compval_, rangeLower, rangeUpper);             tasks.Add(Task.Run<int>(() => { return task.calc(); }));         }         var result = await Task.WhenAll(tasks);         foreach (Task<int> task in tasks)         {             resultCount += task.Result;         }         return resultCount;     } } class task {     public async Task calc()     {         int resultCount = 0;         ・・・時間のかかる処理・・・         return resultCount;     } }

上記のコードでは、taskクラスを生成して、そこからメソッドを呼んでいる。
大体のサンプルでは、FindSumRangeクラスのメソッドを呼ぶ形になっているが、引数に渡した値が書き換えられてしまって、実際には使い物にならなかった。(なのでクラスを生成するようにしたのだが) ←githubに置いてみた
重要な点は、以下の3か所

  • Task<int> result = fsr.calc();
    result.Wait();
  • tasks.Add(Task.Run<int>(() => { return task.calc(); }));
    ・・・
    var result = await Task.WhenAll(tasks);
    foreach (Task<int> task in tasks) { resultCount += task.Result; }
  • public async Task<int> calc()
    {
        int resultCount = 0;
        ・・・時間のかかる処理・・・
        return resultCount;
    }

calc()はint型戻り値を返したいので、Task<int>型の戻り値にする。呼び出し側では、result.Wait()で全スレッドの終了を待つ。結果はResultプロパティで取得できる。

呼び出され側のcalc()では、Task.Run<int>(()=>{return task.calc();}))で並行実行を起動し、その並行実行を管理するためにList<Task<int>>にリストに追加していく。ちなみにtask.calc()はint型を返したいので
すべて並行実行の起動ができたら、終了待ちとして、await Task.WhenAll(tasks)で待つ。(これいるのかな?)

時間が掛かる処理は、並列実行でint型を返したいので、async Task<int>という風に宣言している。

という感じ。

続きを読む "C#で並列実行" »

2016年5月 7日 (土)

Excel VBAの小ネタ 3つ

(1)全てのシート名を取得する

for each a in ActiveWorkbook.Sheets : Debug.Print a.name : next 
Sheet1
Sheet2
Sheet3

(2)特定のシートにある複数のセルの内容を取得する

for each a in ActiveWorkbook.Sheets("sheet1").range("B1:B3") : Debug.Print a.value : next 
a
b
c

(3)セルに入れたシート名にリンクを貼る

for each a in ActiveWorkbook.Sheets("sheet1").range("A1:A3") : a.HyperLinks.Add Anchor:=a, Address:="", SubAddress:=a.value & "!A1" : next 

Excel_cellsworks

2016年4月24日 (日)

「詳細設計書不要」「コメント不要」について

「詳細設計書不要」「コメント不要」について。
これらは「不要な(と思われる)ものを作るのに工数を掛けたくない」「メンテの範囲を少なくしたい」という欲求からの発言であろう。

そも「詳細設計書」「コメント」も必要性があって存在する。
それを無視して一概に不要というべきではない。
無論、不要論を唱える者のはその者なりの理由があるのは分かる。

いわく、コード=詳細設計書なのだから、コードを読めばいい。コードから詳細設計書を作ればいい。
いわく、コーディングしてみないと、出来るか分からない。
いわく、コードを修正したら、詳細設計書も修正しなければならない。でも出来ないことがあるから差異が出てしまい、意味がない。コメントも同様。意味が無いものを作る必要性はあるだろうか。いやない(反語)。

でも待ってくれ。それってオカシイと思わない?
詳細設計書の存在意義は、コーディングする前に設計するためにある。設計工程で不明点を明確にしたり、モジュール間の整合性を取ったりするのだ。(加えて言うなら、設計書からテストを起こす。本来、あるべき動作(仕様)を確認するのがテスト。コードからテストを作るのではない!)
コード=設計仕様書なのではなく、要件定義→外部設計→詳細設計→コーディングの流れの一つの工程で結果的にコード=設計仕様書となるだけ。時間がないから詳細設計書を書けなくてコーディングと詳細設計を同時に行い、コードから詳細設計書を作るという本末転倒なチームや顧客は居る。だけど、それはオカシイ。オカシイ作業がまかり通っているだけ。そして、そういう所は大概、品質が悪く、保守性が悪く、失敗プロジェクトが多い。
作業の意味を考えず、必要な作業をすっとばしているのだから当たり前だ。

一方、コメントは(詳細設計のように)工程の一部ではないので、入れる義務はないと思われるかもしれない。
でも、コメントは”保守性”を高めるために、機能の意味を説明するためにある。
”保守性”は工程ではなく、もっと長いスパン(システムの寿命)で必要となるものである。
「コードは読めば分かるように書く」というのは、もっともなのだが、それにはチームの文化を全員が保持しており、そのコードの保守をその文化を持ったメンバが保守できることが前提となる。
でもチームのメンバがずっと同じであることはほとんどないだろう。企業は、組織の硬直化を防ぐために、チームのメンバが変える必要がある。チームからみると構築された役割が壊され品質を下げるようなデメリットしか感じないだろうが、様々な知識や方法論を広げるという役割がある。

何にしろ、存在意義を無視して特定の条件でしか成り立たない危うい過激な意見に同意しても、益はない。存在意義を理解し、その上で改善を行い、成果物を排除できるような環境を作るってのはありかもしれないけれど、それって環境を育てるのに時間がかかるし、あっという間に壊れそうだよね。素直に詳細設計書をちゃんと作る、コメントをちゃんと入れる、メンテもちゃんと行うって確認するルールを作って運用する方がナンボも簡単だと思うんだけど。

2015年12月 2日 (水)

オイラ、dockerしてるぜ dockerでリバースプロキシを使う

★2017/2/19:「gitlabが起動エラーになる」「Apacheが起動エラーになる」問題を修正。古いDockerImageが残っていて、gitlabでパラメタの設定がないときエラーになるように修正されていた、Apacheのパスとlibxml2.soの展開先が変わっていた。

DockerでCI(継続的インテグレーション)のAPとして、Redmine、Jenkins、gitlab(+redis)と、それらの外部IFとしてApacheHTTPServerをリバースプロキシを立ち上げる環境を構築しようとして紆余曲折していたが、やっとまともにログインまで出来るようになった。
READMEはまだ書いていないけれど、githubにUPしておきました。
Docker ToolBoxをインストールして、Docker Quickstart TerminalでVMイメージを作ったら、そこからinit.shを実行するのです。
シェルを呼び出したディレクトリの直下に、ciディレクトリを作りそこの下に永続化が必要なファイルを出力しますのです。
※:安定して起動できない感じ。シェルの実行が終わっても、環境が起動し終わるまで5分くらい待った方がイイみたい?

init.shを実行した次回からはstart.shを実行することで、Dockerコンテナの起動ができます。
Dockerコンテナの終了はstop.shを実行。

Oracle VM VirtualBoxは、休止状態には対応していない模様で、外部とのアクセスができなくなってしまうので注意。そこら辺の解決方法は、こちらに書いたので参照のこと。

「オイラ、dockerしてるぜ 覚書:DockerのホストOSとSSHで接続できないときの対処」

あと、Oracle VM VirtualBoxからネットワークの設定をしないと、そのPCからしかアクセスできないので注意。アダプタ1(割り当てNAT)のポートフォワーディングにホストIPにそのPCのIPアドレス、ホストポートとゲストポートに80または443を設定(ゲストIPは空欄で可)にすれば、そのPC外からDockerのApacheHTTPServerにアクセスできるようになる。(もちろん、Dockerを動かしているPCで他にポート80を使うAPを動かしていないこと)

ここからはどうでもいい苦労話。

想定としては、http://192.168.99.100/<各AP名>/ というURLにして、パスでAPの割り振りをしようとしていた。これはLocationディレクティブにProxyPassとProxyPassReverseを使って設定できる。

でもこれだけでは、以下の2つの問題が発生してなかなか解決できなかったのだ。

  • CSSやイメージファイル(PNG)が読み込めない。リンクの先が想定外なところに飛ぶ。
    →HTMLのリンク先が正しくないため。
     DockerのそれぞれのWeb・APサーバがHTMLで示すCSSやイメージ、リンク先をAPのパスとは関係なく、設定されるため。
     相対パスだからURL+相対パスとなると思っていたが、そうはならなかった。
  • ログインができない。
    →Cookieのドメイン、パスが正しくないため。
     ProxyPassReverseCookieDomainとProxyPassReverseCookiePathで設定できると思っていたが、Locationディレクティブの外で指定していたので、複数APに対応するProxyPassReverseCookieDomainの内、一番上の方に書かれた設定だけが有効になった模様。
     Webブラウザの開発環境でCookieを見ると、パスが付いていないことから分かった。

というわけで、前者は、mod_proxy_htmlを使って、ProxyHTMLEnable ONとして、ProxyHTMLURLMap で / を /<AP名>/に置き換えることで解決する。(相対パスと言っても"/"で始まるものはルートからになるということを初めて知りましたよ)
後者は、ProxyPassReverseCookieDomainとProxyPassReverseCookiePathをLocationディレクティブの内に書くことで、リバースプロキシに渡されたURLの(APごとの)パスで、区別されたCookieのDomain・パスに変換できるようになる。
#ところでパスの綴りはPass?なのPathなの?

最終的にhttpd.confは以下の定義となる。(元の定義から追加した箇所を抜粋)

LoadFile    /opt/bitnami/common/lib/libxml2.so
LoadModule  proxy_html_module    modules/mod_proxy_html.so
LoadModule  xml2enc_module       modules/mod_xml2enc.so

ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>

<Location /jenkins/>
ProxyPass http://ci_jenkins:8080/jenkins/
ProxyPassReverse http://ci_jenkins:8080/jenkins/

ProxyHTMLEnable On
ProxyHTMLURLMap /jenkins/ /jenkins/

ProxyPassReverseCookieDomain ci_jenkins:8080 192.168.99.100
ProxyPassReverseCookiePath /jenkins/ /jenkins/

RequestHeader unset  Accept-Encoding
</Location>

<Location /redmine/>
ProxyPass http://ci_redmine/
ProxyPassReverse  http://ci_redmine/

ProxyHTMLEnable On
ProxyHTMLURLMap / /redmine/

ProxyPassReverseCookieDomain ci_redmine 192.168.99.100
ProxyPassReverseCookiePath / /redmine/

RequestHeader unset  Accept-Encoding
</Location>

<Location /gitlab/>
ProxyPass http://ci_gitlab/
ProxyPassReverse  /

ProxyHTMLEnable On
ProxyHTMLURLMap / /gitlab/

ProxyPassReverseCookieDomain ci_gitlab 192.168.99.100
ProxyPassReverseCookiePath / /gitlab/

RequestHeader unset  Accept-Encoding
</Location>

ApacheHTTPServerは、bitnami/apacheを使用したがこれにはmod_proxy_htmlが入っていないので、以下のコマンドでインストールして、新たなDockerイメージを作った。


docker run -d --rm=false -v ${apache_dir}/app:/app -v ${apache_dir}/conf:/bitnami/apache/conf -v ${apache_dir}/logs:/bitnami/apache/logs -p 80:80 -p 443:443 ${images6} 

a=`docker ps | grep ${images6} | awk '{print $1}'`
docker exec -it ${a} apt-get -y update
docker exec -it ${a} sudo apt-get -y install libapache2-mod-proxy-html
docker exec -it ${a} apt-get -y install libxml2-dev
docker exec ${a} ln -s /usr/lib/apache2/modules/mod_proxy_html.so /opt/bitnami/apache2/modules/
docker exec ${a} ln -s /usr/lib/apache2/modules/mod_xml2enc.so /opt/bitnami/apache2/modules/
docker commit ${a} apache_rp
docker stop ${a}
docker rm ${a}

ここら辺は、githubに入れたinit.shを見てください。

より以前の記事一覧