0

.csproj ファイル内の参照で < SpecificVersion> が False に設定されていないことを検出する C# 正規表現を作成しようとしています (すべての < の後にスペースを追加して、StackOverflow で正しく表示されるようにする必要がありました)。したがって、これらは私が処理する必要があるケースです:

1. <Reference Include="IQ.MyStuff1, Version=4.1.0.0, Culture=neutral, processorArchitecture=MSIL" />
2. <Reference Include="IQ.MyStuff2, Version=4.7.22.21777, Culture=neutral, processorArchitecture=MSIL">
    <HintPath>..\..\DebugDLLFiles\IQ.MyStuff2.dll</HintPath>
</Reference>
3. <Reference Include="IQ.MyStuff3, Version=4.1.0.0, Culture=neutral, processorArchitecture=MSIL">
    <HintPath>..\..\DebugDLLFiles\IQ.MyStuff3.dll</HintPath>
    <SpecificVersion>True</SpecificVersion>
</Reference>
4. <Reference Include="IQ.MyStuff4, Version=4.5.3.17401, Culture=neutral, processorArchitecture=MSIL">
    <SpecificVersion>True</SpecificVersion>
</Reference>

したがって、基本的には、「< SpecificVersion>False< /SpecificVersion>」が明示的に含まれていないファイル参照です。

最初のケースは、他の 3 つのようなボディを持たず、別の方法で処理できるため、無視しましょう。だからここに私がこれまで持っているものがあります:

<Reference(\s|\n|\r)*?  # Match against '<Reference '.
Include=""IQ\..*?""     # Match against the entire Include attribute; We only care about IQ DLLs.
(\s|\n\r)*?>            # Eat any whitespace and match against the closing tag character.
[What should go here?]
</Reference>            # Match against the closing tag.

[What should go here?] ブロックでさまざまなことを試しましたが、完全に機能するものはないようです。私が最も近づいたのは、このブロックに次を使用することでした:

(?!                     # Do a negative look-ahead to NOT match against this Reference tag if it already has <SpecificVersion>False</SpecificVersion>.
    (.|\n|\r)*?         # Eat everything before the <SpecificVersion> tag, if it even exists.
    <SpecificVersion>(\s|\n|\r)*?False(\s|\n|\r)*?</SpecificVersion>    # Specify that we don't want to match if this tag already has <SpecificVersion>False</SpecificVersion>.
)
(.|\n|\r)*?             # Eat everything after the <SpecificVersion> tag, if it even existed.

これは、照合したいものの下に有効な参照がある場合を除いて、すべてのケースで機能します。有効な参照は次のようになります。

<Reference Include=\"IQ.MyStuff5, Version=4.5.3.17401, Culture=neutral, processorArchitecture=MSIL\">
    <SpecificVersion>False</SpecificVersion>
</Reference>

私が使用している先読みは < /Reference> タグで止まらないようですが、ファイル全体を調べ続けて、その下のテキストに「< SpecificVersion>False< /SpecificVersion>」が含まれていないことを確認します。

最初に遭遇した「< /Reference>」で先読みを停止するにはどうすればよいですか。または、私の問題を解決する別の方法がある場合は、それも受け入れます。任意の提案をいただければ幸いです。ありがとう。

4

3 に答える 3

3

正規表現をあきらめます。それは運命です。XMLじゃない?なぜそれをそのように扱わないのですか?

正規表現で HTML を解析しない」というルールは、XML にも同様に適用されます。

于 2012-04-25T00:33:35.997 に答える
2

とにかく正規表現を試してみたい場合は、次のようなものをお勧めします。

<Reference[^>]*?>(?:.(?!</Reference>))*?<SpecificVersion>([^<]*?)</SpecificVersion>

内部にタグを持つすべてのタグに一致します。つまり、タグを持たない参照タグは完全に無視されます。

  • Referenceタグを探します
  • タグが見つかるまで、参照終了タグ以外のすべてに一致します
  • 次に、タグ内の値をキャプチャします

regexpal でオンラインでテストしたところ、複数のケースで正しく動作するようです。

編集:

  • RegexOptions.Singleline を使用して、ドットを改行に一致させます

SpecificVersion タグがまったく存在しない場合に大文字と小文字を一致させたい場合は、この変更を試してください。オプションをタグと一致させますが、失敗した場合でも、

<Reference[^>]*?>(?:.(?!</Reference>))*?(<SpecificVersion>([^<]*?)</SpecificVersion>)|<Reference[^>]*?>(?:.(?!</Reference>))*?(?:<SpecificVersion>([^<]*?)</SpecificVersion>)?

調子を教えてください。

于 2012-04-25T12:27:17.487 に答える
0

したがって、支出者のアドバイスに従って、正規表現の代替案を調べました。私は Linq To XML を発見し、私の問題を非常に簡単に解決してくれました。これが私の問題を解決するために使用を終了したコードです。.csproj ファイル内の IQ DLL ファイルへのすべての参照を検出し、それらすべてに < SpecificVersion>False< /SpecificVersion> 要素があることを確認します。背景情報として、これを行う必要がある理由は、Specific Version が True に設定されている場合、ビルドがローカル マシンで正常に実行されるためですが、False に設定されていない限り、TFS ビルド サーバーでは機能しなくなるためです。この理由は、TFS ビルドがバージョン番号を更新するため、各プロジェクトが使用するように設定されているバージョンが古くなっているためだと確信しています。とにかく、ここにコードがあります:)

// Let's parse us some XML!
XElement xmlFile = XElement.Load(filePath);

// Grab all of the references to DLL files.
var iqReferences = xmlFile.Descendants().Where(e => e.Name.LocalName.Equals("Reference", StringComparison.InvariantCultureIgnoreCase));

// We only care about iQ DLL files.
iqReferences = iqReferences.Where(r => r.Attribute("Include") != null && r.Attribute("Include").Value.StartsWith("IQ.", StringComparison.InvariantCultureIgnoreCase));

// If this project file doesn't reference any iQ DLL files, move on to the next project file.
if (!iqReferences.Any())
    continue;

// Make sure they all have <SpecificVersion> set to False.
foreach (XElement reference in iqReferences)
{
    // If this Reference element already has a child SpecificVersion element whose value is false, skip this reference since it is good.
    if (reference.Elements().Where(e => e.Name.LocalName.Equals("SpecificVersion", StringComparison.InvariantCultureIgnoreCase))
        .Any(e => e.Value.Equals("False", StringComparison.InvariantCultureIgnoreCase)))
        continue;

    // Add this reference to the list of bad references.
    badReferences.AppendLine("\t" + reference.Attribute("Include").Value);

    // Fix the reference.
    reference.SetElementValue(reference.Name.Namespace + "SpecificVersion", "False");
}
于 2012-04-27T15:35:56.240 に答える