6

「検索」ノードから情報を読み取り、それを使用して検索を実行できる Xpath ステートメント (1.0) を作成しようとしています。

私はいくつかの素晴らしい進歩を遂げていましたが、属性 (検索の値に使用される) が空であるか存在しない場合に失敗するという問題に出くわしました。

簡単にするために編集されたコード 例:

だからここに私のサンプルXMLがあります:

<xml>
    <files>
        <file name="foo" description="" rating="4"/>
        <file name="food" description="" rating="4"/>
        <file name="foobar" description="" rating="3"/>
        <file name="bar" description="" rating="3"/>
        <file name="barter" description="" rating="3"/>
        <file name="barterer" description="" rating="2"/>
    </files>
    <searches>
        <search id="1">
            <exclude>
                <file term="foo"/>
            </exclude>
        </search>
    </searches>
</xml>

そして動作中のXPATH:

//files/file[
            not(contains(@name, //search[@id='1']/exclude/file/@term))
]

それは期待どおりに動作します...

ただし、予期される属性が欠落しているか空の場合、機能しません。contains(@attrib, "") は何らかの理由ですべてに一致するため、属性が "" であるか存在しない場合、 not() は常に何にも一致しません。

たとえば、XML の除外フラグメントをこれに変更すると失敗します。

            <exclude>
                <file term=""/>
            </exclude>

これも:

            <exclude></exclude>

空の値をチェックして選択を実行しない方法はありますか? または、おそらくロジックを構造化するより良い方法があります。Xpath2.0ではConditionalsやその他の関数を使用できないことに注意してください。

4

3 に答える 3

2

検索パラメーターが空白または欠落している場合、Xpath関数contains()がすべてを返すのはなぜですか?

XPath 仕様では、contains()関数がすべきことは次のとおりです。

$arg2 の値が長さ 0 の文字列の場合、関数は true を返します。

XPath を調整し、次のように条件の一部を簡素化できます。

//files/file[
            (  
                (
                    not(//search[@id='1']/include/file/@term)
                    or
                    (
                    contains(@name, //search[@id='1']/include/file/@term) 
                    or
                    contains(@description, //search[@id='1']/include/file/@term) 
                    ) 
                )
                or
                contains(@rating, //search[@id='1']/include/file/@rating)   
            )    
            and 
            ( 
                 (
                    not(//search[@id='1']/exclude/file/@term)
                    or
                    (
                    not(contains(@name, //search[@id='1']/exclude/file/@term)) 
                    and
                    not(contains(@description, //search[@id='1']/exclude/file/@term))
                    )
                )
                and
                (
                    not(//search[@id='1']/exclude/file/@rating)
                    or
                    not(contains(@rating, //search[@id='1']/exclude/file/@rating))
                )
            )

            ]
于 2012-09-02T16:43:35.610 に答える
0

みたいなことを言いたいのかもしれません。

//files/file[
   not(contains(@name, 
                //search[@id='1']
                /exclude/file/@term))
   or not(
     normalize-string(//search[@id='1']
                      /exclude/file/@term)
   )
]
于 2012-09-13T02:11:11.770 に答える