Ошибка вычисления выражения xpath

I;m using XPath to parse XML document returned by a URL, when i run my code with given inputs it works but when giving it inputs as a user input it throws an exception.
The Code:

    class{
        private String generalQuery =  "//@*";
    method(){
        System.out.println("Enter URL");
        url = scan.nextLine();
        URL oracle = new URL(url);
        InputStream is = oracle.openStream();

        org.w3c.dom.Document doc = null;
        DocumentBuilderFactory domFactory;
        DocumentBuilder builder;

        try {
            domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true);
            builder = domFactory.newDocumentBuilder();
            doc = builder.parse(is);
        } catch (Exception ex) {
            System.err.println("unable to load XML: " + ex);
        }

    Map <String, String> params = new HashMap<String, String> ();

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            xpath.setNamespaceContext(new NameSpaces(doc));
            XPathExpression expr = xpath.compile(generalQuery);
            Object result = expr.evaluate(doc, XPathConstants.NODESET); // exception thrown here

            NodeList nl = (NodeList) result;

            for (int i = 0 ; i < nl.getLength() ; i++){
                Node n = (Node)nl.item(i);
                params.put(n.getNodeName(), n.getNodeValue());
            }

            return params;
}
}

The Exception:

javax.xml.transform.TransformerException: Unable to evaluate expression using this context

The class NameSpaces :

import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import org.w3c.dom.Document;

public class NameSpaces implements NamespaceContext {
    private Document sourceDocument;

    public NameSpaces(Document document) {
        sourceDocument = document;
    }

    @Override
    public String getNamespaceURI(String prefix) {
        if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
            return sourceDocument.lookupNamespaceURI(null);
        } else {
            return sourceDocument.lookupNamespaceURI(prefix);
        }
    }

    @Override
    public String getPrefix(String namespaceURI) {
        return sourceDocument.lookupPrefix(namespaceURI);
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        return null;
    }
}

asked May 20, 2013 at 11:19

Muhammed Refaat's user avatar

Muhammed RefaatMuhammed Refaat

8,86413 gold badges82 silver badges117 bronze badges

4

The exception «Unable to evaluate expression using this context» may also result from a null document when trying to evaluate an XPath expression. (I had the same error and it took me a while to figure out I did not initialize my document properly).

In your code you have

try {
  // load document
}
catch (Exception ex) {
  System.err.println("unable to load XML: " + ex);
}

// happily continue

This is a call for trouble. If an exception happens during initialization you should STOP right there and you should not continue. If you have absolutely no idea how to handle the error, use catch(Exception e) { throw new Error(e); }. This will cause exceptions to bubble up and hopefully be handled by the default exception handler which prints a stack trace and exits.

As the reader of your question I don’t even know where the exception was thrown. You should provide this information. Note that you can also use someException.printStackTrace(); to get the stack trace which points you to the correct line.

answered Feb 13, 2014 at 12:12

yankee's user avatar

yankeeyankee

38.5k15 gold badges103 silver badges160 bronze badges

1

What you seem to be missing is a NameSpaceContext that you can implement yourself.

Also see this thread: NamespaceContext and using namespaces with XPath

Example:

class NamespaceResolver implements NamespaceContext {

    private final Document document;

    public NamespaceResolver(Document document) {
        this.document = document;
    }

    public String getNamespaceURI(String prefix) {
        if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
            return document.lookupNamespaceURI(null);
        } else {
            return document.lookupNamespaceURI(prefix);
        }
    }

    public String getPrefix(String namespaceURI) {
        return document.lookupPrefix(namespaceURI);
    }

    @SuppressWarnings("rawtypes")
    public Iterator getPrefixes(String namespaceURI) {
        // not implemented
        return null;
    }

}

Then you initiate the XPath instance like this:

    getXPath().setNamespaceContext(new NamespaceResolver(doc));

Community's user avatar

answered May 20, 2013 at 14:51

User0's user avatar

User0User0

5643 silver badges10 bronze badges

3

In my case this was not due to a null document, but due to an empty document with no root element. Appending the latter solved the issue.

answered Jun 15, 2018 at 10:56

Monkey Supersonic's user avatar

   yyyuuu

naïve

30.09.21 — 10:17

Всем привет ребята. Вопрос. Хочу разобрать [URL=https://dropmefiles.com/kHZA4]XML[/URL]

[CODE]Если ЭлементgetInvoiceReplyВагон <> Неопределено Тогда[/CODE]

Тут сразу получаю Неопределено

Весь код

[CODE]

    
    
    ЧтениеХМЛ = новый ЧтениеXML;

    ЧтениеХМЛ.УстановитьСтроку(Ответ);

    ПостроительDOM = Новый ПостроительDOM;

    ДокументDOM = ПостроительDOM.Прочитать(ЧтениеХМЛ);

    
    РезультатРазборки = Новый Массив;

    
    Разименователь = Новый РазыменовательПространствИменDOM(ДокументDOM);

    
    РезультатgetInvoiceReply = ДокументDOM.ВычислитьВыражениеXPath(«getInvoiceReply»,ДокументDOM.ЭлементДокумента,Разименователь);

    
    Пока Истина Цикл

        //

        ЭлементgetInvoiceReply = РезультатgetInvoiceReply.ПолучитьСледующий();

        Если ЭлементgetInvoiceReply = Неопределено Тогда

            Прервать;

        КонецЕсли;

        
        InvoiceReply = Новый Структура(«carNumber,Tariff,Грузополучатель»);

        
        ЭлементgetInvoiceReplyВагон = ДокументDOM.ВычислитьВыражениеXPath

        («carNumber»,ЭлементgetInvoiceReply,Разименователь).ПолучитьСледующий();

        Если ЭлементgetInvoiceReplyВагон <> Неопределено Тогда

            //

            InvoiceReply.carNumber = ЭлементgetInvoiceReplyВагон;

            //

        КонецЕсли;    

        
        //

    КонецЦикла;    

[/CODE]

Что Я делаю не так?

   Kassern

1 — 30.09.21 — 10:24

(0) в переменной Ответ у вас что?

   yyyuuu

naïve

2 — 30.09.21 — 10:26

(1)сам текст XML

   Kassern

3 — 30.09.21 — 10:33

(0) ну так ошибка то какая в чем проблема?

   youalex

4 — 30.09.21 — 10:33

у меня вот так находит:

getInvoiceReply/invCar/carNumber

   yyyuuu

naïve

5 — 30.09.21 — 10:34

(3)

Ошибок нет, не читает нехрена.

   Kassern

6 — 30.09.21 — 10:34

СП: Если выражение XPath содержит ошибки или в процессе вычисления выражения не удалось разыменовать префикс пространства имен, то будет вызвано исключение.

   youalex

7 — 30.09.21 — 10:35

invCar еще узел в модели.

   yyyuuu

naïve

8 — 30.09.21 — 10:35

(4) Странно у Меня нет. А если из тега getInvoiceReply хочу получить значение?

   youalex

9 — 30.09.21 — 10:36

(8) так ты можешь сразу нужный путь указать к нужным элементам, из контекста ДокументDOM

   yyyuuu

naïve

10 — 30.09.21 — 10:41

(9)

РезультатgetInvoiceReply = ДокументDOM.ВычислитьВыражениеXPath(«getInvoiceReply»,ДокументDOM.ЭлементДокумента,Разименователь);

ЭлементgetInvoiceReply = РезультатgetInvoiceReply.ПолучитьСледующий();

ЭлементgetInvoiceReplyВагон = ДокументDOM.ВычислитьВыражениеXPath

        («getInvoiceReply»,ЭлементgetInvoiceReply,Разименователь).ПолучитьСледующий();

        Если ЭлементgetInvoiceReplyВагон <> Неопределено Тогда

            //

            InvoiceReply.carNumber = ЭлементgetInvoiceReplyВагон;

            //

        КонецЕсли;    

Не работает. И ошибок нету. И доступа к элементам

   yyyuuu

naïve

11 — 30.09.21 — 10:42

РезультатgetInvoiceReply = ДокументDOM.ВычислитьВыражениеXPath(«getInvoiceReply»,ДокументDOM.ЭлементДокумента,Разименователь);

ЭлементgetInvoiceReply = РезультатgetInvoiceReply.ПолучитьСледующий();

        Если ЭлементgetInvoiceReply = Неопределено Тогда

            Прервать;

        КонецЕсли;

Делаю проверку на неопределенно, чтобы выйти из цикла. Сюда сразу падает неопределенно

   Kassern

12 — 30.09.21 — 10:45

(0) а зачем так в цикле обходить с прерыванием? Почему нельзя напрямую обратиться к массиву и обойти все его элементы?

   youalex

13 — 30.09.21 — 10:45

СтрокаЗапроса = «/getInvoiceReply/invCar/carNumber»;

Результат = документДОМ.ВычислитьВыражениеXPath(СтрокаЗапроса, документДОМ, Новый РазыменовательПространствИменDOM(документДОМ));

   yyyuuu

naïve

14 — 30.09.21 — 10:46

(12) проблема в нехватке знаний. Знаю как вот так делать. Если есть пример, поделись

   Kassern

15 — 30.09.21 — 10:57

(14) можно в дерево значений загнать XML, а потом удобно читать, можно еще проще через фабрику сделать как например тут: https://infostart.ru/public/311011/

Там пример с  ФабрикаXDTO.ПрочитатьXML();

   yyyuuu

naïve

16 — 30.09.21 — 10:59

(15)Да Я видел. Но хотел через xpath попробовать. Не могу найти примеров, все как по учебнику делаю а все ровно не получаю доступ к тегам после getInvoiceReply

   youalex

17 — 30.09.21 — 11:01

(16) (13) попробуй

   yyyuuu

naïve

18 — 30.09.21 — 12:34

(17) Результат пустой.

   eklmn

19 — 30.09.21 — 14:17

   yyyuuu

naïve

20 — 05.10.21 — 05:31

(19)

Я  вобще хочу разобрать то что в тегах -<getInvoiceReply> и +<invCar>

   yyyuuu

naïve

21 — 06.10.21 — 03:50

Вроде разобрался с getInvoiceReply а как перебрать узлы <invCar> их от 4 до 5 бывает

   yyyuuu

naïve

22 — 06.10.21 — 04:18

РезультатgetInvCar = ДокументDOM.ВычислитьВыражениеXPath(«//getInvoiceReply/invCar»,ДокументDOM.ЭлементДокумента,Разименователь);

        ЭлементInvCar = РезультатgetInvCar.ПолучитьСледующий();

        
        ЭлементgetInvoiceReplyНомВаг = ДокументDOM.ВычислитьВыражениеXPath

        («//carNumber»,ЭлементInvCar,Разименователь).ПолучитьСледующий();

        
        ЭлементgetInvoiceReplyНомВаг = ДокументDOM.ВычислитьВыражениеXPath

        («//getInvoiceReply/invCar/*»,ЭлементInvCar,Разименователь).ПолучитьСледующий();

        
        Пока ЭлементgetInvoiceReplyНомВаг <> Неопределено  Цикл

            //

            ЭлементgetInvoiceReplyНомВаг = ДокументDOM.ВычислитьВыражениеXPath

            («//getInvoiceReply/invCar/carNumber»,ЭлементInvCar,Разименователь).ПолучитьСледующий();

            InvoiceReply.invNumber =  ЭлементgetInvoiceReplyНомВаг.ПолучитьАтрибут(«value»);

            Сообщить(InvoiceReply.invNumber);

            ч = ч +1;

            Если ч>7 Тогда прервать; КонецЕсли;

            
            //

        КонецЦикла;

Пробую так перебать <invCar> их от 1-20 может быть. НЕ работает, попадаю всегда только на первый элемент первого тега <invCar>

   yyyuuu

naïve

23 — 06.10.21 — 04:56

ЭлементЭлементgetInvoiceReply= ДокументDOM.ВычислитьВыражениеXPath(«/getInvoiceReply»,ДокументDOM.ЭлементДокумента,Разименователь);

        
        Если ЭлементЭлементgetInvoiceReply <> Неопределено тогда

            Пока Истина Цикл

                //

                InvoiceReply.invCar = Новый Массив;

                РезультатПоискgetInvoiceReply_invCar = ДокументDOM.ВычислитьВыражениеXPath(«/invCar»,ЭлементЭлементgetInvoiceReply,Разименователь);

                Пока Истина Цикл

                    //

                    Элемент_InvoiceReply_invCar = РезультатПоискgetInvoiceReply_invCar.ПолучитьСледующий();

                    Если Элемент_InvoiceReply_invCar = Неопределено Тогда

                        Прервать;

                    КонецЕсли;

                    
                    Строка_invCar = Новый Структура(«сarNumber»);

                    
                    Элемент_InvoiceReply_invCar_invCarNumber = ДокументDOM.ВычислитьВыражениеXPath(«/carNumber»,Элемент_InvoiceReply_invCar,Разименователь);

                    Если Элемент_InvoiceReply_invCar_invCarNumber <> Неопределено Тогда

                        Строка_invCar.сarNumber = Элемент_InvoiceReply_invCar_invCarNumber.ПолучитьАтрибут(«value»);                        

                    КонецЕсли;    

                    //

                КонецЦикла;    

                //

            КонецЦикла;

        КонецЕсли;

Ошибка по причине:

{ВнешняяОбработка.РазборХМЛ.МодульОбъекта(161)}: Ошибка при вызове метода контекста (ВычислитьВыражениеXPath)

по причине:

Несоответствие типов (параметр номер ‘2’)

  

yyyuuu

naïve

24 — 06.10.21 — 08:14

(19) спасибо

 <?xml version="1.0" encoding="ISO-8859-1" ?> 
- <OrderFeed>
- <Order id="1">
- <BillingInformation>
  <Name>Bruce Ganek</Name> 
  <Address>99 Main Street</Address> 
  <City>Cranston</City> 
  <State>RI</State> 
  <ZipCode>02910</ZipCode> 
  </BillingInformation>
- <ShippingInformation>
  <Name>Governor Chafee</Name> 
  <Address>82 Smith St # 115</Address> 
  <City>Providence</City> 
  <State>RI</State> 
  <ZipCode>02903-1121</ZipCode> 
  </ShippingInformation>
- <Items>
- <Item>
  <PartNo>JETSWEATER</PartNo> 
  <Description>N.Y. Jets Sweatshirt</Description> 
  <UnitPrice>10.50</UnitPrice> 
  <Quantity>2</Quantity> 
  <TotalCost>21.00</TotalCost> 
- <CustomerOptions>
  <Size>M</Size> 
  <Color>Green</Color> 
  </CustomerOptions>
  </Item>
- <Item>
  <PartNo>JETSWEATER</PartNo> 
  <Description>N.Y. Jets Sweatshirt</Description> 
  <UnitPrice>7.50</UnitPrice> 
  <Quantity>3</Quantity> 
  <TotalCost>22.50</TotalCost> 
- <CustomerOptions>
  <Size>S</Size> 
  <Color>White</Color> 
  </CustomerOptions>
  </Item>
- <Item>
  <PartNo>JETSFLASHLIGHT</PartNo> 
  <Description>N.Y. Jets Flashlight</Description> 
  <UnitPrice>5.00</UnitPrice> 
  <Quantity>1</Quantity> 
  <TotalCost>5.00</TotalCost> 
  <CustomerOptions /> 
  </Item>
  </Items>
  </Order>
- <Order id="2">
- <BillingInformation>
  <Name>Walt Disney</Name> 
  <Address>DisneyWorld Hotel</Address> 
  <City>Orlando</City> 
  <State>FL</State> 
  <ZipCode>32801</ZipCode> 
  </BillingInformation>
- <ShippingInformation>
  <Name>Walt Disney</Name> 
  <Address>DisneyWorld Hotel</Address> 
  <City>Orlando</City> 
  <State>FL</State> 
  <ZipCode>32801</ZipCode> 
  </ShippingInformation>
- <Items>
- <Item>
  <PartNo>JETSWEATER</PartNo> 
  <Description>N.Y. Jets Sweatshirt</Description> 
  <UnitPrice>10.50</UnitPrice> 
  <Quantity>2</Quantity> 
  <TotalCost>21.00</TotalCost> 
- <CustomerOptions>
  <Size>M</Size> 
  <Color>Green</Color> 
  </CustomerOptions>
  </Item>
- <Item>
  <PartNo>JETSWEATER</PartNo> 
  <Description>N.Y. Jets Sweatshirt</Description> 
  <UnitPrice>7.50</UnitPrice> 
  <Quantity>3</Quantity> 
  <TotalCost>22.50</TotalCost> 
- <CustomerOptions>
  <Size>S</Size> 
  <Color>White</Color> 
  </CustomerOptions>
  </Item>
- <Item>
  <PartNo>JETSFLAG</PartNo> 
  <Description>N.Y. Jets Flag for display</Description> 
  <UnitPrice>5.00</UnitPrice> 
  <Quantity>1</Quantity> 
  <TotalCost>5.00</TotalCost> 
  <CustomerOptions /> 
  </Item>
  </Items>
  </Order>
- <Order id="3">
- <BillingInformation>
  <Name>Tom Brady</Name> 
  <Address>One Patriot Place</Address> 
  <City>Foxboro</City> 
  <State>MA</State> 
  <ZipCode>02035</ZipCode> 
  </BillingInformation>
- <ShippingInformation>
  <Name>Tom Brady</Name> 
  <Address>2121 George Halas Drive</Address> 
  <City>Canton</City> 
  <State>OH</State> 
  <ZipCode>44708</ZipCode> 
  </ShippingInformation>
- <Items>
- <Item>
  <PartNo>JETPANTS</PartNo> 
  <Description>N.Y. Jets Sweatpants</Description> 
  <UnitPrice>10.50</UnitPrice> 
  <Quantity>3</Quantity> 
  <TotalCost>31.50</TotalCost> 
- <CustomerOptions>
  <Size>M</Size> 
  <Color>Green</Color> 
  </CustomerOptions>
  </Item>
- <Item>
  <PartNo>JETSWEATER</PartNo> 
  <Description>N.Y. Jets Sweatshirt</Description> 
  <UnitPrice>7.50</UnitPrice> 
  <Quantity>1</Quantity> 
  <TotalCost>7.50</TotalCost> 
- <CustomerOptions>
  <Size>S</Size> 
  <Color>White</Color> 
  </CustomerOptions>
  </Item>
- <Item>
  <PartNo>JETSFLAG</PartNo> 
  <Description>N.Y. Jets Flag for display</Description> 
  <UnitPrice>5.00</UnitPrice> 
  <Quantity>1</Quantity> 
  <TotalCost>5.00</TotalCost> 
  <CustomerOptions /> 
  </Item>
  </Items>
  </Order>
  </OrderFeed>

Выше приведен XML-документ, который я анализирую. Моя цель состоит в том, чтобы использовать для ввода PartNo, скажем, например, «JETSFLAG» — это строка, которую они передают в приложение. Я хочу найти все заказы в OrderFeed и подсчитать, сколько раз был куплен конкретный PartNo. У меня есть инструмент XPath Navigator, который по какой-то причине ничего не возвращает, когда я пишу выражение, которое должно работать, чтобы получить то, что я хочу.

Вот что я получаю в результате, когда оцениваю выражение: //OrderFeed/Order/Items//Item//PartNo которое дает мне нужные мне данные, все, что мне нужно, это подсчет любого конкретного элемента, который вводит пользователь…

  <xml>JETSWEATER JETSWEATER JETSFLASHLIGHT JETSWEATER JETSWEATER JETSFLAG JETPANTS JETSWEATER JETSFLAG</xml> 

Теперь я почти уверен, что запись count(//OrderFeed/Order/Items//Item//PartNo[JETSFLAG]) должна привести к подсчету 2 элементов. Но это то, что мне возвращается…

  <xml>0</xml> 

Я получаю 0 для подсчета, когда он отображается. Кто-нибудь может помочь?

Я пытаюсь проанализировать большой XML файл, и я использую много относительного пути для выражений XPath.

Теперь у меня возникают проблемы с оценкой .net XPath.

Вот небольшой пример, который объясняет мою проблему:

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>

<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
</book> 
</bookstore>

И вот код:

static void Main(string[] args)
{
    System.Xml.XmlDocument d = new System.Xml.XmlDocument();
    d.Load(@"D:simpleXml.xml");

    System.Diagnostics.Trace.WriteLine(d.SelectSingleNode("//price/..[year='2005']").Name);
}

Появляется следующее сообщение об ошибке:
Дополнительная информация: ‘//price/..[year=’2005’] ‘имеет недопустимый токен.

Для меня это похоже на допустимое выражение XPath, поскольку другие инструменты, такие как XMLSpy, успешно оценивают это выражение.

Я пытаюсь разобрать большой XML-файл и использую много относительных путей для выражений XPath.

Теперь у меня проблемы с оценкой.net XPath.

Вот небольшой пример, который объясняет мою проблему:

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>

<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
</book> 
</bookstore>

И вот код:

static void Main(string[] args)
{
    System.Xml.XmlDocument d = new System.Xml.XmlDocument();
    d.Load(@"D:simpleXml.xml");

    System.Diagnostics.Trace.WriteLine(d.SelectSingleNode("//price/..[year='2005']").Name);
}

Я получаю следующее сообщение об ошибке: Дополнительная информация: ‘//price/..[year=’2005’]’имеет недопустимый токен.

Мне кажется, это правильное выражение XPath, поскольку другие инструменты, такие как XMLSpy, успешно оценивают это выражение.

2012-10-22 14:20

2
ответа

Почему бы не использовать linq2xml

XDocument doc=XDocument.Load("yourXML");

var bookPrice=doc.Descendants("book")
.Where(x=>x.Element("year").Value=="2005")
.Select(y=>y.Element("price").Value);
//gets the price of the books published in 2005

Если вы хотите версию xpath, вот она

"bookstore/book[year='2005']/*/../price"
//gets the price of the books published in 2005

2012-10-22 14:53

Если вы посмотрите на спецификацию XPath по адресу http://www.w3.org/TR/xpath/, мы увидим, что производство Step определяется как:

Step  ::=  AxisSpecifier NodeTest Predicate*    
         | AbbreviatedStep

Другими словами, предикат не может следовать за сокращенным шагом, таким как. или.. Я бы предположил, что реализация поэтому (строго) правильна. Возможно, XMLSpy немного более либерален в своей интерпретации и просто всегда расширяется.. до parent:node()?

2012-11-01 13:47

Понравилась статья? Поделить с друзьями:
  • Ошибка высокое напряжение бортовой сети
  • Ошибка выжившего что значит выражение
  • Ошибка выгрузки на терминале ingenico
  • Ошибка времени фильм 2019
  • Ошибка времени на компьютере как исправить