delphi
  • xpath
  • msxml
  • 2009-10-05 5 views 4 likes 
    4

    Я загрузил XML-документ, и теперь я хочу запустить запрос XPath для выбора определенного подмножества XML. XML являетсяDelphi/MSXML: запросы XPath не удается

    <?xml version="1.0"?> 
    <catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> 
        <book id="bk101"> 
         <author>Gambardella, Matthew</author> 
         <title>XML Developer's Guide</title> 
         <genre>Computer</genre> 
         <price>44.95</price> 
         <publish_date>2000-10-01</publish_date> 
         <description>An in-depth look at creating applications with 
         XML.</description> 
        </book> 
    </catalog> 
    

    и процедура идет что-то вроде

    procedure RunXPathQuery(XML: IXMLDOMDocument2; Query: string); 
    begin 
    
        XML.setProperty('SelectionLanguage', 'XPath'); 
    
        NodeListResult := XML.documentElement.selectNodes(Query)); 
    
        ShowMessage('Found (' + IntToStr(NodeListResult.length) + ') nodes.'); 
    
    end; 
    

    проблема: когда я выполнить запрос XPath «/ каталог» для выше XML, он возвращает (как и ожидалось) нодлист из 1 элемент. Однако, если я удалю :xsi из <catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> и повторно запустим запрос, возвращаемый нодлист пуст. Если я удалю весь атрибут «xmlns», то в результате в списке узлов появится еще один элемент.

    Итак, мой вопрос заключается в следующем: что я могу сделать, чтобы исправить это, т. Е. Как заставить MSXML возвращать правильное количество экземпляров (при выполнении запроса XPath), независимо от пространства имен (или других атрибутов)?

    Спасибо!

    +0

    Либо я читаю это (http://support.microsoft.com/kb/288147) совершенно неправильно, или его невозможно использовать пространство имен по умолчанию с XPath для определенных версий MSXML. К сожалению, я использую MSXML v6.0, поэтому это не должно меня повлиять. У кого-то был подобный опыт? – conciliator

    ответ

    3

    См. this link!

    Когда вы используете <catalog xmlns='http://www.w3.org/2001/XMLSchema-instance'>, тогда весь узел будет перемещен в другое (по умолчанию) пространство имен. Ваш XPath не ищет внутри этого другого пространства имен, поэтому он не может найти какие-либо данные. С <catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> вы просто объявляете xsi как другое пространство имен. Это будет другое пространство имен, чем пространство имен по умолчанию.

    я не могу проверить это прямо сейчас, но добавляя что-то like this может помочь:

    XML.setProperty('SelectionNamespaces', 'xmlns=''http://www.w3.org/2001/XMLSchema-instance'''); 
    

    Или, может быть, это не так. Как я уже сказал, я не могу проверить это прямо сейчас.

    +0

    Спасибо, мастерская Алекс! Это имеет большой смысл. К сожалению, это, похоже, не делает трюк (пока), но я буду играть с ним немного больше. – conciliator

    1

    Использование:

    document.setProperty('SelectionNamespaces', 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"') 
    
    +0

    ... и затем запросить '/ xsi: catalog' вместо'/catalog'. –

    2

    Фигурные его. Кажется, что моя проблема была описана here и here (и, скорее всего, еще миллион других мест).

    Запрос/* [local-name() = 'catalog'] работает для меня.

    0
    /*[local-name()='catalog'] 
    

    - решение на ваш вопрос. Но почему вы хотите игнорировать пространства имен? Они были введены, чтобы выразить что-то, например. различать разные типы каталогов. По вашему запросу теперь вы можете выбрать контент любого каталога в мире, но я предполагаю, что вы можете обрабатывать книги. Что произойдет, если вместо этого вы получите каталог винтов или автомобилей?

    Указанное о префиксе (xsi) верно. Если вы удалите префикс, все элементы находятся в этом пространстве имен (тогда будет использоваться пространство имен по умолчанию). Но вы все еще можете справиться с этим.

    В вашем коде дайте пространству имен префикс в любом случае. Он не должен совпадать даже с исходным префиксом:

    XML.setProperty('SelectionNamespaces', "xmlns:xyz='http://www.w3.org/2001/XMLSchema-instance'"); 
    

    Во-вторых, нужно приспособить запрос XPath.Затем должно быть

    /xyz:catalog 
    

    Исходный XML объявляет пространство имен xsi, но никогда не использует его. В этом случае вы можете полностью удалить его. Если вы хотите использовать пространство имен, и вы хотите его с приставками, а затем переписать XML в

    <?xml version="1.0"?> 
    <xsi:catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> 
        <xsi:book id="bk101"> 
        <xsi:author>Gambardella, Matthew</xsi:author> 
        <xsi:title>XML Developer's Guide</xsi:title> 
        <xsi:genre>Computer</xsi:genre> 
        <xsi:price>44.95</xsi:price> 
        <xsi:publish_date>2000-10-01</xsi:publish_date> 
        <xsi:description>An in-depth look at creating applications with 
        XML.</xsi:description> 
    </xsi:book> 
    </xsi:catalog> 
    
    Смежные вопросы