2016-04-27 23 views
1

私はXPath(1.0)を使用して、それ自体または任意の祖先が特定のパラメーター値を持つ特定の型のすべての要素を取得しようとしています。トリックは、パラメータが値のリストになることができるので、@ parameter = 'value'を探すだけではできません。これは、私の場合のための文書の一例であり、それらまたはその祖先のいずれかのいずれかを持っているのは、私は外部参照要素を探しています言わせプラットフォーム=「モバイル」:XPath先祖または自己解決の順序

<doc> 
    <block> 
     <xref platform="mobile desktop">1</xref> 
    </block> 
    <block platform="mobile"> 
     <xref platform="desktop">2</xref> 
    </block> 
    <block platform="desktop"> 
     <xref platform="mobile">3</xref> 
    </block> 
</doc> 

I(いくつかの助けを借りて)目標は、同時に外部参照の祖先と自分自身のためのプラットフォームのすべての値を連結するための連結のためだった、とモバイルがそこにあったならば、参照

//xref[contains(concat(' ', normalize-space(ancestor-or-self::*/@platform), ' '), ' mobile ')] 

:ほとんどそれを作るように見える次のXPathを思い付きました。したがって、サンプルドキュメントでは3つの外部参照をすべて返す必要がありますが、3つ目の外部参照は省略します。私は先祖または自己がルートレベルから評価していると思うので、実際に残りの祖先または自己をチェックすることなく、モバイルではないプラットフォームが見つかると失敗します。さらに、この動作では、一度に1つのノードのプラットフォーム値だけを見ているので、連結は実際に何もしません。

誰もこの特定のケースを解決する方法を知っていますか?

答えて

1

なり、与えられたノード集合は、その集合の最初のノードのみを評価する。したがって、次の式が最初platformの属性を発見し評価します:

normalize-space(ancestor-or-self::*/@platform) 

ような問題を回避するために、OPの未遂XPathは次のようにビットを微調整することができます。

//xref[ 
    ancestor-or-self::*[ 
     contains(concat(' ', normalize-space(@platform), ' '), ' mobile ') 
    ] 
] 

デモ:xpathtesterxpatheval

このように、文字列関数は、platform個の属性ancestor-or-self要素。

+0

ありがとう、これは私が探していたものです!私は一点で似たようなことを試していたことを知っていたので、私は自分の試みを見て、このようなものを見つけました。正直言って私はなぜそこにいるべきではないのかを理解することはできませんが、ありがとう! –

+0

@AndresMataようこそ!私はそれを次のように考えるでしょう:述語( '[...]')はコンテキストノードを適用する必要があり、コンテキストは左のノードです。 '/ ancestor-or-self :: * [...]'との対比以外は、述語の左には何もないので、 '/ [...]'は正しい構文ではありません。 'ancestor-or-self :: *'は述語のコンテキストになります – har07

1

//xref[contains(@platform, 'mobile')] | //xref/ancestor::*[contains(@platform, 'mobile')]/xref 

以下のXPathは私を与える:

<xref platform="mobile desktop">1</xref> 
<xref platform="desktop">2</xref> 
<xref platform="mobile">3</xref> 
+0

私の質問ではあまり明確ではなかったかもしれませんが、このxpathにはいくつかの問題があります。別のプラットフォームの値が "fakemobile"である可能性があります。それは "モバイル"部分文字列が十分ではない、それは別のプラットフォームの値の一部かもしれないが含まれています。もう一つの問題は、値を持つ外部参照の直接の祖先ではないということです。これはどんな祖先でもかまいません...しかし、これはたくさんありがとうございます –

+0

あなたの問題を明確にしてください..ありがとうございます。 – SomeDude

1

Iがあるときにそうnormalize-space(ancestor-or-self::*/@platform)がエラーを与えるだろうので、あなたはおそらく、XPath 1.0のを(あなたが本当に言うべき)を使用していると思います複数の属性が選択されています。

XPath 1.0では、この式はノード順序のノードの最初のノードに文書順に適用されます。これは最上位の@プラットフォームであり、祖先はその子孫の前にドキュメントの順序で先行するためです。一番内側の@platformが必要な場合は、normalize-space((ancestor-or-self::*/@platform)[last()])を使用してください。

しかし、あなたは、任意の祖先列として「モバイル」含む@Platformを持っている要素を選択している場合、それは、XPath 1.0、文字列パラメータを期待normalize-space()のような文字列関数で

//xref[ancestor::*/@platform[contains(., 'mobile')]] 
+0

はい、申し訳ありませんが、私はXPathを学んでいますので、バージョンの違いを認識していませんでした。私はJava 8でjavax.xml.xpathライブラリを使用しており、ドキュメントによればXPath 1.0に準拠しています。モバイルではなく、この答えを展開する簡単な方法は、リストの値の1つに一致するプラットフォームの部分文字列ですか?たとえば、platform = "desktop mobileBrowser"ではなく、platform = "desktop mobile"と一致することができます。私はそのようなケースが2つあります。 –

+0

Javaを使用している場合は、XPath 1.0に限定する必要はありません。XPath 2.0または3.0、またはXQueryを実装する製品がいくつかありますが、これははるかに強力です。私自身のSaxon製品もその1つです。しかし、すでに使用しているトリックで1.0のマッチを行うことができます:述語を '[contains(concat( ''、normalize-space(。)、 '')、 'mobile')に変更してください。 –

関連する問題