努力したWiki

推敲の足りないメモ書き多数

ユーザ用ツール

サイト用ツール


documents:etl:pentaho:pentaho-012

文書の過去の版を表示しています。


KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUEの件

KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUEをYにしていると、ステップ「XMLデータ取得(Get data from XML)」でXPathに関数を使えない。
Pentaho 9.4 でも Pentaho 10.2でも再現する。

音声解説

Google NotebookLMで音声解説を作ってもらいました。動画はまだ英語のみなんだけど近日中に他言語にも対応するとの事。



パラメタ整理

データベースでの空データとnullの扱いを調整するためのパラメタ KETTLE_EMPTY_STRING_DIFFERS_FROM_NULL の追加が発端の模様。
https://github.com/pentaho/pentaho-kettle/commit/6d0e66de465e25f2623614e2e9971f42be3673bc

区別が必要になったためか、他にもパラメタが新設された。KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUEもそのうちの一つ。

# プロパティ 説明 デフォルト 設定値等
1 KETTLE_EMPTY_STRING_DIFFERS_FROM_NULL Pentaho全体でのnull値扱い指定 N デフォルトはnullとemptyを区別しない
Yを指定するとnullとemptyを区別する
2 KETTLE_DO_NOT_NORMALIZE_NULL_STRING_TO_EMPTY nullの文字列をemptyに変換するか否か N デフォルトはnullをemptyへ変換する
Yを指定するとnullをemptyへ変換しない
3 KETTLE_XML_EMPTY_TAG_YIELDS_EMPTY_VALUE 空タグ時、値にnullを生成するか否か N デフォルトはnullを生成する
Yを指定するとnullを生成しない(empty)
4 KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUE 指定タグが無い場合nullを生成するか否か N デフォルトはemptyを生成する
Yを指定するとnullを生成する

empty : ISBLANK()=Trueになる値

推理

https://github.com/pentaho/pentaho-kettle/blob/5441e5bbc35c1e2a02b6cf36db01cb5a2e0277f2/plugins/xml/core/src/main/java/org/pentaho/di/trans/steps/getxmldata/GetXMLData.java

KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUE=Y で事が起こるのは、XPathの関数をノード(タグ)だと思って探しに行く処理になっているのではないかと。
※このパラメタ有効時は、すべてノード(タグ)だと思って処理しているもしくは関数が来ることを想定していない

GitHubリポジトリのコードが現行と一致すると仮定する。
KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUE=Y の時はSelectSingleNodeメソッドを使うようだけど、ノード検索メソッドならXPath関数は当然ヒットしない。
ValueOfメソッドはXPath関数の評価まで面倒を見てくれているんじゃないかな。

追加検証

うるさい人が湧いたので実際にコード書いて確かめよう。

検証用のコードはこちら。

xpathCheck.java
package xpathCheck;
 
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
 
public class XPathCheck {
 
	public static void main(String[] args) {
 
		boolean xmlMissingTagYieldsNullValue = false; // KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUE=N を模す※デフォルト  
 
		String filePath = "D:\\pleiades\\sampledata\\Sample.xml";
		String xpathExpression = "count(/root/employees/employee)";
 
        	SAXReader rdr = new SAXReader()	;
        	String nodeValue;
 
        	try {
        	    Document doc = rdr.read(filePath);
 
        	    // KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUE 問題処理の再現
        	    if(xmlMissingTagYieldsNullValue)
        	    {
            		nodeValue = doc.selectSingleNode(xpathExpression) != null ? doc.valueOf(xpathExpression) : null;
        	    }
        	    else
        	    {
            		nodeValue = doc.valueOf(xpathExpression);	
        	    }
 
        	    System.out.println("XPath: " + xpathExpression);
        	    System.out.println("Node Value: " + nodeValue);
 
    	        } catch (Exception e) {
        	    e.printStackTrace();
    	        }
 
        }
}

入力データはこちら。

Sample.xml
<root>
 
  <employees>
 
    <employee>
      <name>hoge</name>
      <desc>hogehoge</desc>
    </employee>
 
    <employee>
      <name>fuga</name>
      <desc>fugafuga</desc>
    </employee>
 
  </employees>
 
</root>

まずデフォルト時(Nが指定された状態)での実行結果。

さて次はオプション指定(Yが指定された状態)状態にする。この個所をfalse→trueに変更して実行。

		boolean xmlMissingTagYieldsNullValue = true; // KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUE=Y を模す※オプション指定状態

実行結果。見た覚えのあるエラーが出てますでしょ?

念のため、関数ではなく存在しないノードの検索にしてみましょうか。

		String xpathExpression = "/root/employees/employee/age";

実行結果。修正者は関数の時もこの状態が来ると思ってあのコードにしたんでしょうね。やっぱりテストケース不足です。

暫定修正

ぶっちゃけ、valueOf()の処理結果とオプション指定を見て、emptyをnullに変えりゃよかったんですよ。

xpathCheck2.java
package xpathCheck;
 
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
 
public class XPathCheck {
 
	public static void main(String[] args) {
 
		boolean xmlMissingTagYieldsNullValue = true; // KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUE=Y を模す  
 
		String filePath = "D:\\pleiades\\sampledata\\Sample.xml";
		String xpathExpression = "count(/root/employees/employee)";
 
        	SAXReader rdr = new SAXReader()	;
        	String nodeValue;
 
        	try {
                    Document doc = rdr.read(filePath);
 
        	    // 暫定的な修正例
                    nodeValue = doc.valueOf(xpathExpression);
                    if((xmlMissingTagYieldsNullValue)&&(nodeValue.length() == 0)) nodeValue = null;
 
                    System.out.println("XPath: " + xpathExpression);
                    System.out.println("Node Value: " + nodeValue);
 
                } catch (Exception e) {
                    e.printStackTrace();
                }
 
	}
}

関数の結果も返るし、

存在しないノードの結果はnullになる。

		String xpathExpression = "/root/employees/employee/age";

documents/etl/pentaho/pentaho-012.1755194410.txt.gz · 最終更新: by k896951

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki