努力したWiki

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

ユーザ用ツール

サイト用ツール


documents:etl:pentaho:pentaho-012

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
documents:etl:pentaho:pentaho-012 [2025/08/19 02:05] – [パラメタ整理] k896951documents:etl:pentaho:pentaho-012 [2026/05/13 03:47] (現在) k896951
行 1: 行 1:
 +====== 200.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で音声解説を作ってもらいました。動画はまだ英語のみなんだけど近日中に他言語にも対応するとの事。
 +
 +{{:documents:etl:pentaho:pasted:nazo.mp3 |Pentahoの謎パラメータ「KETTLEXMLMISSINGTAGYIELDSNULLVALUE」徹底解説:XPath関数が動かなくなる真の理由と賢い解決策}}\\ \\ 
 +
 +===== 発端 =====
 +
 +開発環境で作った.ktr定義を本番に近い環境でテストしたら、XMLの入力だけエラーになる。\\ みんなで頭抱えてたところ、同僚氏が執念に近い献身で差異調査を行って件のパラメタの設定で発生する事を見つけた。いやほんとよく見つけたよ。
 +
 +===== パラメタ整理 =====
 +
 +この事象の始まりは、データベースでの空データとnullの扱いを調整するためのパラメタ KETTLE_EMPTY_STRING_DIFFERS_FROM_NULL の追加をした事。\\ 
 +https://github.com/pentaho/pentaho-kettle/commit/6d0e66de465e25f2623614e2e9971f42be3673bc
 +
 +データベース以外にXMLでも要望があったのか#3,#4の専用パラメタが新設された。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関数の評価まで面倒を見てくれているんじゃないかな。
 +{{.:pasted:20250812-041630.png?nolink}}
 +
 +===== 追加検証 =====
 +
 +うるさい人が湧いたので実際にコード書いて確かめよう。
 +
 +検証用のコードはこちら。
 +<code java 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();
 +            }
 +
 +        }
 +}
 +</code>
 +
 +入力データはこちら。
 +<code xml Sample.xml>
 +<root>
 +
 +  <employees>
 +
 +    <employee>
 +      <name>hoge</name>
 +      <desc>hogehoge</desc>
 +    </employee>
 +    
 +    <employee>
 +      <name>fuga</name>
 +      <desc>fugafuga</desc>
 +    </employee>
 +
 +  </employees>
 +  
 +</root>
 +</code>
 +
 +まずデフォルト時(Nが指定された状態)での実行結果。\\ 
 +{{.:pasted:20250814-093523.png?nolink}}
 +
 +さて次はオプション指定(Yが指定された状態)状態にする。この個所をfalse→trueに変更して実行。
 +<code java>
 + boolean xmlMissingTagYieldsNullValue = true; // KETTLE_XML_MISSING_TAG_YIELDS_NULL_VALUE=Y を模す※オプション指定状態
 +</code>
 +
 +実行結果。見た覚えのあるエラーが出てますでしょ?\\ 
 +{{.:pasted:20250814-093837.png?nolink}}
 +
 +念のため、関数ではなく存在しないノードの検索にしてみましょうか。
 +<code java>
 + String xpathExpression = "/root/employees/employee/age";
 +</code>
 +
 +実行結果。修正者は関数の時もこの状態が来ると思ってあのコードにしたんでしょうね。やっぱりテストケース不足です。\\ 
 +{{.:pasted:20250814-095935.png?nolink}}
 +
 +===== 暫定修正 =====
 +
 +ぶっちゃけ、下手にY or Nの条件分岐なんてせずに、valueOf()の処理結果とオプション指定を見て、emptyをnullに変えりゃよかったんですよ。
 +
 +<code java 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();
 +                }
 +
 + }
 +}
 +
 +</code>
 +
 +関数の結果も返るし、\\ 
 +{{.:pasted:20250814-101403.png?nolink}}
 +
 +存在しないノードの結果はnullになる。\\ 
 +<code java>
 + String xpathExpression = "/root/employees/employee/age";
 +</code>
 +{{.:pasted:20250814-102218.png?nolink}}
documents/etl/pentaho/pentaho-012.txt · 最終更新: by k896951

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki