2010-01-04 4 views
4

В моем приложении у меня есть известное смещение интереса к XML-строке и вы хотите ответить на такие вопросы, как «что такое мой родительский элемент?». без разбора всего документа.Есть ли обратный XML-парсер для .NET?

Этот article упоминает библиотеку, которая, как представляется, находится в Objective-C для «обратного» разбора XML. Мое приложение не требует полной поддержки XML, поэтому я рад смириться со всеми предостережениями о невозможности синтаксического анализа полностью. Есть ли что-то подобное для C# /. NET?

Уточнение: Я не спрашиваю о разборе решений или компромиссных решениях в целом, меня интересуют конкретные ситуации, когда я нахожусь в какой-то момент на полпути через текстовый поток и просто хочу знать что-то о локальной структуре. Представьте себе ситуацию, когда я не хочу получать верх документа, потому что доступ имеет очень высокую задержку.

ответ

2

Похоже, XPathDocument может быть тем, что вы ищете. Этот класс обеспечивает быстрое, доступное только для чтения представление в формате XML документа XML. Он не создает DOM и оптимизирован для запросов XPath.

XPathDocument также может использоваться для анализа фрагментов XML. Для этого вам необходимо создать его с XmlReader, который имеет уровень соответствия, установленный для фрагмента.

В следующем примере кода первым выбирает набор узлов XML из фрагмента XML, а затем выбирает родительский каждый узел на основе выражения XPath:

using System; 
using System.IO; 
using System.Xml; 
using System.Xml.XPath; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     string xml = File.ReadAllText(@"C:\tmp\smplInput.xml"); 

     XmlReaderSettings xrs = new XmlReaderSettings(); 
     xrs.ConformanceLevel = ConformanceLevel.Fragment; 

     using (TextReader textReader = new StringReader(xml)) 
     { 
      using (XmlReader xmlReader = XmlReader.Create(textReader, xrs)) 
      { 
       // Create a new XPathDocument 
       XPathDocument doc = new XPathDocument(xmlReader); 

       // Create navigator 
       XPathNavigator navigator = doc.CreateNavigator(); 

       // Set up namespace manager for XPath 
       XmlNamespaceManager ns = new XmlNamespaceManager(navigator.NameTable); 
       ns.AddNamespace("w", "http://www.example.com/2010/"); 

       // Select nodes 
       XPathNodeIterator users = navigator.Select("//w:user", ns); 

       while (users.MoveNext()) 
       { 
        XPathNavigator user = users.Current; 
        XPathNavigator department = user.SelectSingleNode("parent::node()", ns); 
        Console.WriteLine(string.Format("User {0} is in department {1}", 
         user.GetAttribute("name", ns.DefaultNamespace), 
         department.GetAttribute("type", ns.DefaultNamespace))); 
       } 
      } 
     } 
    } 
} 

попробовать код, который вы могли бы использовать следующий XML входной документ:

<?xml version="1.0" encoding="utf-8" ?> 
<w:departments xmlns:w="http://www.example.com/2010/"> 
    <w:department type="A"> 
    <w:user name="w" /> 
    <w:user name="x" /> 
    <w:department type="B"> 
     <w:user name="x" /> 
     <w:user name="y" /> 
    </w:department> 
    <w:department type="C"> 
     <w:user name="x" /> 
     <w:user name="y" /> 
     <w:user name="z" /> 
    </w:department> 
    </w:department> 
    <w:department type="D"> 
    <w:user name="w" /> 
    </w:department> 
</w:departments> 
+0

Можете ли вы привести пример того, как я могу использовать его для достижения этого? В обычном способе использования XPathDocument я все равно передаю ему целую строку, не указывая, где должен начинаться синтаксический анализ строки. – kdt

+0

Я добавил пример. Просто передайте всю строку и выполните ваши запросы XPath, чтобы выбрать интересующие узлы. Полагаться, что текстовое смещение не кажется хорошей идеей. В большинстве случаев XPathDocument должен работать с разумной производительностью. Поэтому, прежде чем пытаться написать собственный синтаксический анализатор, я бы попробовал и посмотрел, получится ли вам достаточно быстрый результат (написание собственного анализатора может показаться немного недопустимым). Также обратите внимание, что производительность может быть оптимизирована путем тонкой настройки запросов XPath. –

+0

Хорошо, поэтому XPathDocument не то, что я ищу - это не общая скорость или эффективность, а конкретный случай, когда я знаю, где в тексте, который я хочу начать, и я хочу полностью избежать поиска в другом месте , Например, у меня есть часть файла, и получение каких-либо других частей будет включать в себя хранение с высокой задержкой, например, ленточный робот. – kdt

3

Это невозможно сделать, не делая существенных предположений о характере вашего текста. Прежде всего, вы должны предположить, что это хорошо сформированный XML и что он не содержит разделов CDATA и пространств имен.

Если вы начинаете в любом месте посреди потока и создаете резервную копию, пока не нажмете то, что кажется началом элемента, вы не можете знать, что текст, на который вы смотрите, фактически - начало элемента. Это может быть CDATA. И вы не можете сказать, что это не CDATA, пока вы не отбросили весь поток, ищущий <![CDATA[ и не нашли его.

Пространства имен представляют собой аналогичную проблему. Если вы найдете начальный тег, например <Foo, вы не можете точно знать, что Foo находится в пространстве имен по умолчанию, пока вы не вернетесь полностью к корневому элементу документа и не убедитесь, что элемент предка не имеет объявления пространства имен. Если вы найдете <x:Foo, вам нужно отступить, пока не найдете закрытый элемент с объявлением xmlns:x.

Если вы точно знаете, что текст хорошо сформированный XML, что он не содержит CDATA и что его использование пространств имен ограничено (то есть вы можете указать, какое пространство имен находится в элементе, просто взглянув на его start tag), то некоторые из того, что вы пытаетесь сделать, по крайней мере, возможны.

Вы можете создать резервную копию до первого начального тега, с которым вы сталкиваетесь, создать StreamReader, чье происхождение это положение, и использовать его для создания XPathDocument, который настроен для обработки фрагментов документа.Обратите внимание, кстати, что у вас нет уверенности, что XPathDocument не будет читать весь путь до конца текста в первый раз, когда вы его используете, кроме того, у вас есть знания о характере текста, и вы знаете, что будет присутствовать соответствующий конечный тег.

Но это не будет обрабатывать конкретный случай, который вы упомянули, т. Е. Находите родительский элемент. Чтобы найти родительский элемент, вам нужно будет найти начальный тег, которому не предшествует (по мере продвижения назад) соответствующий тег конца. Это не очень сложно сделать - каждый найденный вами персонаж < станет началом либо стартового тега, либо конечного тега, либо пустого элемента, и вы можете просто положить теги конца в стек и выскочить, когда вы найдете их соответствующий начальный тег. Когда вы нажимаете начальный тег, и стек пуст, вы находитесь в начале родительского элемента.

Но это тоже процесс, который может привести к вашим возвратам всего пути происхождения ручья, особенно в тривиальном случае, когда XML вы ищете является классический идиотским форматом журнал XML:

<log> 
    <entry>...</entry> 
    <entry>...</entry> 

... повторяется до бесконечности

1

Другой подход для разбора XML один раз, а затем генерировать индекс XML так что в следующий раз при загрузке индекса и не нужно разобрать XML несколько раз ... в статье ниже

http://xml.sys-con.com/node/453082

+0

Джимми, пожалуйста, поймите, что есть некоторые вопросы, на которые VTD не ответ. Это одна из них. Вот полезная ссылка ... http://meta.stackexchange.com/questions/21823/what-constitutes-spam – kdt

+1

нет ничего плохого в том, чтобы предлагать общий подход, а не конкретный ответ ... почему эта ссылка даже релевантная ?? –

+0

@kdt: Из вопроса, который вы задали, неясно, что VTD не может быть интересным подходом. «Я нахожусь в какой-то момент на полпути через текстовый поток и просто должен знать что-то о локальной структуре». Это похоже на VTD, если вы уже создали индекс. И независимо от того, собираетесь ли вы использовать VTD или нет, предварительная индексация вашего XML может решить вашу актуальную проблему. Возможно, вам нужно дать более подробную информацию в своем вопросе, так как кажется, что все ответы пока не соответствуют вашим требованиям. –

0

CAX от xponentsoftware делает именно то, что вы хотите.

Смежные вопросы