Xpathの豊富な機能をすべて使用して、「if」を実行できるようです。しかし、私のエンジンは「そのような機能はありません」と主張し続けており、ウェブ上でドキュメントを見つけることはほとんどありません(疑わしいソースを見つけましたが、構文は機能しませんでした)
文字列の末尾から「:」を削除する必要がある場合(存在する場合)、これを実行したかったのです。
if (fn:ends-with(//div [@id='head']/text(),': '))
then (fn:substring-before(//div [@id='head']/text(),': ') )
else (//div [@id='head']/text())
何かアドバイス?
はい、XPath 1.0でそれを行う方法があります。
concat( substring($ s1、1、number($ condition)* string-length($ s1))、 substring($ s2、1、number(not( $ condition))* string-length($ s2)) )
これは、2つの相互に排他的な文字列の連結に依存しています。最初の文字列は、条件がfalseの場合は空(0 * string-length(...)
)で、2番目の文字列は条件がtrueの場合は空です。これは "Beckerのメソッド"と呼ばれ、 Oliver Becker に起因します。
あなたの場合:
concat( substring( substring-before(// div [@ id = 'head']/text()、 ':')、 1 、 number( ends-with(// div [@ id = 'head']/text()、 ':') ) * string -length(substring-before(// div [@ id = 'head']/text()、 ':')) )、 substring( // div [@ id = 'head']/text()、 1、 number(not( ends-with(// div [@ id = 'head']/text()、 ':') )) * string-length(// div [@ id = 'head']/text()) ) )
私はすべての"//"
前。
また、//div[@id='head']
は複数のノードを返します。
注意してください— //div[@id='head'][1]
はより防御的です。
W3.orgの XPath 2. の公式言語仕様は、言語がifステートメントを実際にサポートすることを詳述しています。特に、 セクション3.8条件式 を参照してください。構文の形式と説明とともに、次の例を示します。
if ($widget1/unit-cost < $widget2/unit-cost)
then $widget1
else $widget2
これは、式を囲む括弧がないことを示唆します(そうでなければ構文は正しいように見えます)。私は完全に自信はありませんが、試してみる価値はあります。したがって、クエリを次のように変更する必要があります。
if (fn:ends-with(//div [@id='head']/text(),': '))
then fn:substring-before(//div [@id='head']/text(),': ')
else //div [@id='head']/text()
ただし、XPathエンジンがif
を関数として解釈しようとしているように見えるため、実際には言語の特別な構成要素であるため、これが修正される可能性があります。
最後に、明白なことを指摘するために、XPathエンジンが(以前のバージョンとは対照的に)XPath 2.0を実際にサポートしていることを確認してください!条件式は以前のバージョンのXPathの一部ではないと思います。
pkaratの法律によると、バージョン1.0で条件付きXPathを実現できます。
あなたの場合、概念に従ってください:
concat(substring-before(your-xpath[contains(.,':')],':'),your-xpath[not(contains(.,':'))])
これは間違いなく機能します。仕組みをご覧ください。 2つの入力を与える
praba:
karan
最初の入力の場合::
が含まれているため、条件が真で、:
の前の文字列が出力になります。たとえば、praba
が出力になります。 2番目の条件はfalseなので問題ありません。
2番目の入力の場合::
が含まれていないため条件が失敗し、2番目の条件になると文字列に:
が含まれないため条件が真になります。したがって、出力karan
がスローされます。
最後に、出力はpraba
、karan
になります。
個人的には、XSLTを使用してXMLを変換し、末尾のコロンを削除します。たとえば、次の入力があるとします。
<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Paragraph>This paragraph ends in a period.</Paragraph>
<Paragraph>This one ends in a colon:</Paragraph>
<Paragraph>This one has a : in the middle.</Paragraph>
</Document>
段落の末尾のコロンを削除したい場合は、次のXSLTを使用します。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="2.0">
<!-- identity -->
<xsl:template match="/|@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- strip out colons at the end of paragraphs -->
<xsl:template match="Paragraph">
<xsl:choose>
<!-- if it ends with a : -->
<xsl:when test="fn:ends-with(.,':')">
<xsl:copy>
<!-- copy everything but the last character -->
<xsl:value-of select="substring(., 1, string-length(.)-1)"></xsl:value-of>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
代わりにfn:replace(string、pattern、replace)を使用してはどうですか?
XPATHはXSLTで非常に頻繁に使用されます。そのような状況でXPATH 2.0がない場合は、次を使用できます。
<xsl:choose>
<xsl:when test="condition1">
condition1-statements
</xsl:when>
<xsl:when test="condition2">
condition2-statements
</xsl:when>
<xsl:otherwise>
otherwise-statements
</xsl:otherwise>
</xsl:choose>
残念ながら、以前の回答は私にとって選択肢ではなかったので、しばらく調査し、この解決策を見つけました:
http://blog.alessio.marchetti.name/post/2011/02/12/the-Oliver-Becker-s-XPath-method
特定のNodeが存在する場合、テキストを出力するために使用します。4はテキストfooの長さです。したがって、よりエレガントな解決策は変数の使用でしょう。
substring('foo',number(not(normalize-space(/elements/the/element/)))*4)
Tomalek(ここに投稿)とDimitre( here )から適応した、やや単純なXPath 1.0ソリューション:
concat(substring($s1, 1 div number($cond)), substring($s2, 1 div number(not($cond))))
注:boolをintに変換するには明示的なnumber()が必要であることがわかりました。それ以外の場合、XPathエバリュエーターは型の不一致エラーをスローしました。 XPathプロセッサがどの程度厳密に型マッチングを行っているかによっては、必要ない場合があります。