2017-08-12 13 views
0

XMLファイル(書籍のデータベース)を照会するC#プログラムを作成しています。
定義済みの著者ですべてのレコードを照会したいとします。<の著者>は、<の著者>のリストとして定義されています。
は、これまで私が使用し、以下:定義済みの子を持つレコードを抽出するXPath式

itemNodes = xmlDoc.SelectNodes("//record[contains(translate(authors/author, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '" + strSearch.ToLower() + "')]"); 

それは、このレコードでOKです:

<record> 
    <_formats>PDF</_formats> 
    <publisher>Alessio Roberti Editore</publisher> 
    <authors sort="Dilts, Robert"> 
    <author>Robert Dilts</author> 
    </authors> 
... 

が、それはこの1ミス:ここ

<record> 
    <_formats>AZW3, EPUB</_formats> 
    <publisher>Alessio Roberti Editore</publisher> 
    <authors sort="Gilligan, Stephen &amp; Dilts, Robert"> 
    <author>Stephen Gilligan</author> 
    <author>Robert Dilts</author> 
    </authors> 
... 

著者が2番目の項目ですリストの
両方のレコードを返すように式を変更するにはどうすればよいですか?

+0

C#を使用しているので、代わりにLinq2Xmlを使用できます。テキスト内の一重引用符の問題を避けるために簡単に使用することができます。 –

答えて

2

両方のレコードを返すように式を変更するにはどうすればよいですか?

十分に簡単です。変更:

"//record[contains(authors/author, '" + strSearch.ToLower() + "')]" 

へ:

"//record[authors/author[contains(., '" + strSearch.ToLower() + "')]]" 

述語を入れ子にすることができます。

言われていること

、代わりにアルファベットをハードコーディングするため、あなたが検索できる文字数を制限する、すべての文字を探して対応するためのC#を使用します。

var strSearch = "Search"; 
var xpath = String.Format(
    "//record[authors/author[contains(translate(., '{0}', '{1}'), '{1}')]]", 
    strSearch.ToUpper(), 
    strSearch.ToLower() 
); 

strSearch場合、これはまだ解除されます一重引用符を含みます。あらかじめそれらを剥がしてください。これは、あなたが(読みやすくするためラップ)を与える:

//record[authors/author[contains(
    translate(., 'SEARCH', 'search'), 
    'search' 
)]] 

代わりの単一引用符を削除し、あなたはそれらを適切に処理することができます。 XPathにはエスケープシーケンスはありませんので、単純に何とかエスケープすることはできません。

O'Connorは、二重引用符で囲まれたXPath:"O'Connor"の文字列で表現できます。'は一重引用符で囲むことはできません(逆も同様)。残念ながら、これは持っていない文字列の内容の事前知識が必要です。

O'Connorと評価されるXPath式を作成することができます。これはconcat('O', "'", 'Connor')です。この種の式には関係なく、それが含まれているどのように多くの単一引用符、任意の入力から自動的に構築することはできない。

string escapeXPath(string input) { 
    if (input.Contains("'")) 
     return "concat('" + String.Join("', \"'\", '", input.Split('\'')) + "')"; 
    return "'" + input + "'"; 
} 

ので、あなたはこのようにそれを組み込むことができます(微妙な違いは、上記のw/R/Tのシングルにあります引用符):ABILを犠牲にすることなく、

//record[authors/author[contains(
    translate(., concat('O', "'", 'CONNOR'), concat('o', "'", 'connor')), 
    concat('o', "'", 'connor') 
)]] 

:あなたの読みやすさのために包まれた安全なXPath 1.0の式を()与え

var strSearch = "O'Connor"; 
var xpath = String.Format(
    "//record[authors/author[contains(translate(., {0}, {1}), {1})]]", 
    escapeXPath(strSearch.ToUpper()), 
    escapeXPath(strSearch.ToLower()) 
); 

一重引用符(またはA〜Z範囲外の文字)を検索する。

+0

ありがとうございますが、* System.Xml.XPath.XPathException:containsに2つの引数を含むプログラムがクラッシュする* – SteMMo

+0

はい、私は自分に気づいた。回答が更新されました。 – Tomalak

+0

@SteMMo 'String.Format()'を使うと、より良いコードになります。再び更新されました。 – Tomalak

関連する問題