Ваш код синтаксического анализа XML должен работать по счастливому пути, когда содержимое XML корректно.
Несмотря на то, что он работает без проблем в «счастливом пути», поскольку вы используете expect
в коде вместо обработки ошибок, программа паникует в сценарии ошибок.
Вы можете изменить код на следующий, чтобы лучше распечатать ошибку:
let package = parser::parse(&contents);
match package {
Ok(package) => {
let document = package.as_document();
let value = evaluate_xpath(&document, "/root").expect("XPath evaluation failed");
println!("value: {:?}", value);
}
Err(err) => {
println!("{:?}", err);
}
}
После этого исправления вы заметите, что код печатает ошибку UnknownNamespacePrefix
.
Эта ошибка возникает, когда содержимое XML имеет пространства имен, которые не объявлены в самом файле XML.
В вашем XML-файле вам нужно указать свои пространства имен, которые вы не указали для следующего:
<organisation xml:id="a17649">
Вам необходимо добавить пространство имен:
<organisation xml:id="a17649" xmlns:rdf="http://www.w3.org/1999/xhtml">
Даже один раз вы объявили rdf
пространство имен таким образом, вы также используете пространство имен dbk
, которое, вероятно, зависит от самого вашего проекта. Вам также нужно будет указать это пространство имен:
<organisation xml:id="a17649" xmlns:rdf="http://www.w3.org/1999/xhtml" xmlns:dbk="/path/to/dbk">
После этих изменений ваша проблема должна быть решена
Я пошел бы для Именованных каналов.
В основном Вам будет нужна уникальная конечная точка на пользователя. Как с Вашим Взаимным исключением, Вы будете, вероятно, использовать имя пользователя для обнаружения названия именованного канала для использования. Это могло бы даже заменить Ваше использование Взаимного исключения: попытайтесь узнать, существует ли именованный канал для этого конкретного уже, и если он делает, это означает, что Вы - второй экземпляр для выполнения.
Более трудно отобразить порт TCP на пользователя.
О, и при помощи Именованных каналов, я на самом деле говорю "Дистанционную работу по Именованным каналам".
Именованные каналы являются обычно лучшими, но также и рассматривают MSMQ для огня и забывают сценарий, который гарантирует доставку сообщений со временем. Это действительно зависит от Ваших размеров сообщения также. TCP стал бы хитрым, потому что Вам будет нужен уникальный порт на пользователя.
Sendmessage/Postmessage и Getmessage являются API, которые я люблю за это.
Sendmessage:
http://pinvoke.net/default.aspx/user32.SendMessage
Постсообщение:
http://pinvoke.net/default.aspx/user32.PostMessage
GetMessage:
http://pinvoke.net/default.aspx/user32.GetMessage
Можно установить объем Взаимного исключения к "сессии, локальной" путем добавления префикса ее имени "Локальный \"; прочитайте MSDN для больше. Таким образом, можно ограничить экземпляры процесса на терминальный сеанс (хорошо, это не точно, что Вы спросили).
IPC - то, что я использовал в прошлом для этого. И это supprisingly легкий. дистанционная работа .NET является хорошим вариантом, но к сожалению это - ограниченная опция becasue, Вы не можете, например, использовать его на CF.
Ниже копия класса, который я использую для выполнения Межпроцессного взаимодействия, можно использовать его в conjuction с MutEx, при необходимости но это не необходимо. Пока "pMappedMemoryName" и "pNamedEventName" являются тем же в обоих процессах, это должно работать просто великолепно. Я пытался сделать его максимально управляемым событиями.
Просто используйте Ввести по абсолютному адресу метод для записи данных и метода Быстрого взгляда для чтения его, хотя я разработал его для автоматического увольнения события, когда новые данные доступны. Таким образом можно просто подписаться на событие IpcEvent и не иметь для волнения о дорогих опросах.
public class IpcService {
private IServiceContext mContext;
const int maxLength = 1024;
private Thread listenerThread;
private readonly string mMappedMemoryName;
private readonly string mNamedEventName;
public event EventHandler<TextualEventArgs> IpcEvent;
private readonly bool mPersistantListener;
public IpcService(bool pPersistantListener)
: this(pPersistantListener, "IpcData", "IpcSystemEvent") {
;
}
public IpcService(bool pPersistantListener, string pMappedMemoryName, string pNamedEventName) {
mPersistantListener = pPersistantListener;
mMappedMemoryName = pMappedMemoryName;
mNamedEventName = pNamedEventName;
}
public void Init(IServiceContext pContext) {
mContext = pContext;
listenerThread = new Thread(new ThreadStart(listenUsingNamedEventsAndMemoryMappedFiles));
listenerThread.IsBackground = !mPersistantListener;
listenerThread.Start();
}
private void listenUsingNamedEventsAndMemoryMappedFiles() {
IntPtr hWnd = EventsManagement.CreateEvent(true, false, mNamedEventName);
while (listenerThread != null) {
if (Event.WAITOBJECT == EventsManagement.WaitForSingleObject(hWnd, 1000)) {
string data = Peek();
EventsManagement.ResetEvent(hWnd);
EventHandler<TextualEventArgs> handler = IpcEvent;
if (handler != null) handler(this, new TextualEventArgs(data));
}
}
EventsManagement.SetEvent(hWnd);
Thread.Sleep(500);
HandleManagement.CloseHandle(hWnd);
}
public void Poke(string format, params object[] args) {
Poke(string.Format(format, args));
}
public void Poke(string somedata) {
using (MemoryMappedFileStream fs = new MemoryMappedFileStream(mMappedMemoryName, maxLength, MemoryProtection.PageReadWrite)) {
fs.MapViewToProcessMemory(0, maxLength);
fs.Write(Encoding.ASCII.GetBytes(somedata + "\0"), 0, somedata.Length + 1);
}
IntPtr hWnd = EventsManagement.CreateEvent(true, false, mNamedEventName);
EventsManagement.SetEvent(hWnd);
Thread.Sleep(500);
HandleManagement.CloseHandle(hWnd);
}
public string Peek() {
byte[] buffer;
using (MemoryMappedFileStream fs = new MemoryMappedFileStream(mMappedMemoryName, maxLength, MemoryProtection.PageReadWrite)) {
fs.MapViewToProcessMemory(0, maxLength);
buffer = new byte[maxLength];
fs.Read(buffer, 0, buffer.Length);
}
string readdata = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
return readdata.Substring(0, readdata.IndexOf('\0'));
}
private bool mDisposed = false;
public void Dispose() {
if (!mDisposed) {
mDisposed = true;
if (listenerThread != null) {
listenerThread.Abort();
listenerThread = null;
}
}
}
~IpcService() {
Dispose();
}
}
Я надеюсь, что это помогает.
.Net Remoting мог бы также быть удобным. Это быстро и легко реализовать.
Иначе должен использовать старый добрый DDE (Динамический обмен данными): http://www.codeplex.com/ndde
DDE основывается на сообщениях окон, но является уровнем абстракции выше его.
(Да, мне нравятся мои друзья API Win32), ;)