Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > как извлечь xml-данные?


Автор: azalia 17.5.2015, 18:47
Доброго времени суток!

Может кто подскажет как правильней запрашивать xml-данные хранящиеся в БД через xpath-выражения при помощи сервлетов и jsp?
Это надо будет в форме <FORM> задавать уже готовые xpath-выражения и передавать их в сервлет, а сервлет уже будет коннектится к БД и доставать согласно этим выражениям нужные данные?

Автор: AntonSaburov 18.5.2015, 09:30
Я бы сделал через отправку XPAth в сервлет, который уже ходил бы в базу, доставал данные и вызывал JSP, которая все это рисовала и выводила бы форму для ввода нового выражения.

Автор: azalia 18.5.2015, 17:48
Не могу отправить данные формы... Что-то видимо насочиняла не то....

Выкладываю что есть на данный момент:

JSP:

Код

<html>
<head>
<title>Books Search</title></head>
<body>
<form action="BooksJsp" method="POST">

<select name="/books/book[@id]"> 
    <option value="/books/book[@id='1']">Книга 1</option>
    <option value="/books/book[@id='2']">Книга 2</option>
</select>
<input type="submit" name="Найти книгу" value="Найти книгу">
</form>
</body>
</html>


Хотя, я такой формы ни разу за всю свою жизнь не видела smile

Сервлет:

Код

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class BooksJsp extends HttpServlet {
 
   public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   response.setContentType("text/html");
   request.setCharacterEncoding("UTF-8");
   PrintWriter out = response.getWriter();
   String inputName=request.getParameter("name");
   String mtd=request.getMethod();
   String url=request.getRequestURI();
   String prt=request.getProtocol();
   if(inputName==null) {
   //response.sendError(505, "Propucheno imya имя");
   out.println("<html><body>");
   out.println("<h3>Вы выбрали книгу:" + inputName+"</h3>");
   out.println("<h3>Metod:" + mtd+"</h3>");
   out.println("<h3>URL:" + url+"</h3>");
   out.println("<h3>Protokol:" + prt+"</h3>");
   out.println("</body></html>");
   } else {
   out.println("<html><body>");
   out.println("<h3>Вы выбрали книгу:" + inputName+"</h3>");
   out.println("<h3>Metod:" + mtd+"</h3>");
   out.println("<h3>URL:" + url+"</h3>");
   out.println("<h3>Protokol:" + prt+"</h3>");
   out.println("</body></html>");
   } 
   }


Вывод браузера:

Код


???? ?????±???°?»?? ??????????:null
Metod:POST
URL:/testApp/BooksJsp
Protokol:HTTP/1.1

Автор: AntonSaburov 19.5.2015, 09:15
Честно говоря я не понял вот это:

<select name="/books/book[@id]"> 
    <option value="/books/book[@id='1']">Книга 1</option>
    <option value="/books/book[@id='2']">Книга 2</option>
</select>

В качестве имени такое выражение "/books/book[@id]" - это что такое ?
Сервлет просит просто параметр name - а в форме фигня какая-то. Вы бы почитали HTML и HTTP на досуге - там много важного и нужного есть.

Автор: mbasil 20.5.2015, 16:43
Ну во-первых не 
response.setContentType("text/html");
а
response.setContentType("text/html,UTF-8");

чтобы текст на кириллице увидеть в ответе

Автор: azalia 20.5.2015, 19:43
Цитата(mbasil @  20.5.2015,  16:43 Найти цитируемый пост)
чтобы текст на кириллице увидеть в ответе 


не помогает...

JSP:

Код

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>


Сервлет:

Код

response.setContentType ("text/html; charset=utf-8");
PrintWriter out = response.getWriter ();
request.setCharacterEncoding ("utf-8");


server.xml

Код

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
           useBodyEncodingForURI="true"
           URIEncoding="UTF-8"/>


этот код тоже не помогает:

Код

out.println("<html>");
out.println("<head>");
out.println("<meta charset='utf-8'>");
out.println("<title></title>");
out.println("</head>");
out.println("<body>");



Может ли быть проблема в старом ПО? IE6, Windows XP...
Установила браузер Chrome 43 - в нем такая же беда...

Может все перевести в windows-1251? или как там...

Автор: mbasil 20.5.2015, 20:39
Чему не помогает?

В случае response.setContentType ("text/html; charset=utf-8");

текст на кириллице должен выводиться.
А поводу получения значения параметра, гсп. Сабуров писал же, что надо запрашивать не "name", а по видимому:

String inputName=request.getParameter("/books/book[@id]");  

Кстати, А зачем Вы дали параметру такое странное имя?

Автор: azalia 20.5.2015, 20:48
Цитата(mbasil @  20.5.2015,  20:39 Найти цитируемый пост)
А поводу получения значения параметра, гсп. Сабуров писал же, что надо запрашивать не "name", а по видимому:

String inputName=request.getParameter("/books/book[@id]");  

Кстати, А зачем Вы дали параметру такое странное имя?



Да, я поменяла name (перепутала раньше), теперь выводится...

Оно такое странное, потому что мне надо как-то сохранить путь xpath в какую-нибудь переменную и потом ее подставлять в запрос к БД. На оригинальность не претендую, я новичок в этом деле.

Автор: mbasil 20.5.2015, 21:05
Имя переменной связано с ее значением не буквально, а мнемонически, а посему должно как имя любой переменной соответствовать смыслу значения, а не содержимому. Просто имена переменным надо давать  пристойные.

Автор: azalia 20.5.2015, 21:06
Цитата(mbasil @  20.5.2015,  20:39 Найти цитируемый пост)
Чему не помогает?

В случае response.setContentType ("text/html; charset=utf-8");

текст на кириллице должен выводиться.


Не помогает замена кода
response.setContentType ("text/html")
на
response.setContentType ("text/html; charset=utf-8");
или на
response.setContentType("text/html,UTF-8");

сейчас картина в браузере такая:

Код

привет ghjg
Contact Name 1XXX-XXX-XXXX


перевожу: привет ghjg = привет ghjg

код:
Код

out.println("<h3>привет ghjg</h3>");


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

Добавлено через 14 минут и 53 секунды
Цитата(mbasil @  20.5.2015,  21:05 Найти цитируемый пост)
Имя переменной связано с ее значением не буквально, а мнемонически, а посему должно как имя любой переменной соответствовать смыслу значения, а не содержимому. Просто имена переменным надо давать  пристойные. 


хорошо, я поняла, спасибо smile
обзову по-другому, только теперь не знаю как выбранное значение обрабатывать дальше в сервлете.

Автор: mbasil 20.5.2015, 21:20
response.setContentType ("text/html; charset=utf-8");
должно работать.
1. Фильтр это только для того, чтобы не писать это каждый раз. Пока нет смысла.
2. Проверьте настройки браузера. Проверьте в другом браузере.
3. Проверьте  кодировку файла с исходным кодом сервлета.
4. Если сервер старый Tomcat, там требовалось в элементе Connector в файле server. xml добавить атрибут seBodyEncodingForURI="true" примерно так (но только в старый, до версии 5 включительно):

    <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
    <Connector port="8080" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true"
               useBodyEncodingForURI="true"/>

 


Автор: azalia 20.5.2015, 21:35
Цитата(mbasil @  20.5.2015,  21:20 Найти цитируемый пост)
1. Фильтр это только для того, чтобы не писать это каждый раз. Пока нет смысла.
2. Проверьте настройки браузера. Проверьте в другом браузере.
3. Проверьте  кодировку файла с исходным кодом сервлета.
4. Если сервер старый Tomcat, там требовалось в элементе Connector в файле server. xml добавить атрибут 


я все уже это проделывала
http://forum.vingrad.ru/index.php?showtopic=383391&view=findpost&p=2639605

использую Notepad++, в нем выставлена кодировка UTF-8 (без BOM), пересохранила еще раз в простом блокноте с выставлением кодировки utf-8...
Томкат 7, свеже установленный...

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

Добавлено через 12 минут и 4 секунды
кстати, вспомнила, а может ли повлиять на кодировку смена пути к Томкат?

раньше у меня Томкат был установлен по пути С:/Tomcat 7.0
я его не переустанавливала, а вручную сменила путь на С:/Tomcat (переименовала папку)
соответсвенно везде перенастроила пути и в реестре windows тоже для запуска службы
а вот где кодировка прописывается - не знаю...

Автор: mbasil 20.5.2015, 21:57
Перемещение, пожалуй, не могло повлиять. Больше предположений нет. В последних версиях Tomcat с подобными казусами я не встречался.
как обрабатывать зависит от того, в какой базе вы XML храните и в каком виде.
У Oracle, например есть тип данных XMLType, он построен над CLOB и в нем можно по хpath  довольно просто находить нужное значение.

Автор: azalia 20.5.2015, 22:11
Цитата(mbasil @  20.5.2015,  21:57 Найти цитируемый пост)
как обрабатывать зависит от того, в какой базе вы XML храните и в каком виде.
У Oracle, например есть тип данных XMLType, он построен над CLOB и в нем можно по хpath  довольно просто находить нужное значение.


в данный момент использую ms sqlserver,  в самой базе без проблем все получается, а вот удаленные запросы пока не очень.
нашла работу с типом sqlxml, пока осваиваю...
получилось пока только запросить данные сплошным текстом, без структуры xml

Автор: mbasil 20.5.2015, 22:35
1. Извлечь "сырой" XML можно посредством запроса с помощью JDBC. В Java встроены XML анализаторы DOM,SAX,STAX,JAXB, поэтому (если не привлекать какие-либо доролнительные фреймворки) можно разобрать извлеченный XML выбранным встроенным средством (ну это конечно потребует усилий), а потом получить, что нужно. 

2.Для проверки кириллицы, чтобы сильно не ломать голову, скачайте и инсталлируйте NetBeans. В него встроены два сервера: Tomcat и GlassFish. Инсталляция проста, можете выбрать только встроенный Tomcat и не ставить GlassFish. Проект заготовки web приложения можно сгенерировать в несколько щелчков мышки. Проверьте, как выводится кириллица. Затем, в случае успеха, скопируйте свои написки в этот проект. Ну уж совсем потом можно NetBeans'ом подцепить ваш Tomcat для чистоты эксперимента и развернуть проект на нем.  Все равно, продолжать работу лучше в графической среде, а не в командной строке. Необходимо только установить CATALINA_HOME на нужную версию Tomcat и не "барахтаться" одновременно с двумя.

Автор: azalia 20.5.2015, 22:54
Цитата(mbasil @  20.5.2015,  22:35 Найти цитируемый пост)
1. Извлечь "сырой" XML можно посредством запроса с помощью JDBC. В Java встроены XML анализаторы DOM,SAX,STAX,JAXB, ................


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

Цитата(mbasil @  20.5.2015,  22:35 Найти цитируемый пост)

2.Для проверки кириллицы, чтобы сильно не ломать голову, скачайте и инсталлируйте NetBeans. ......... 


хорошо попробую так, если места хватит на виртуальной машине...

Автор: mbasil 21.5.2015, 07:55
Я не слишком хорошо знаю MSSQL, так что возможно имеются средства базы, позволяющие запрос по xpath.

Автор: azalia 21.5.2015, 10:08
А эта ошибка о чем говорит? Не определен такой объект?

Код

Tool Finished with exit code 1
Error in line Number:55: error: cannot find symbol
    Document document = (Document) domSource.getNode();
    ^
  symbol:   class Document
  location: class BooksJsp
Error in line Number:55: error: cannot find symbol
    Document document = (Document) domSource.getNode();
                         ^
  symbol:   class Document
  location: class BooksJsp
2 errors

Автор: LSD 21.5.2015, 12:19
Цитата(azalia @  21.5.2015,  11:08 Найти цитируемый пост)
А эта ошибка о чем говорит? Не определен такой объект?

Не импортирован. Нормальная IDE сразу покажет такую ошибку и предложит пути решения.

Автор: azalia 21.5.2015, 18:30
Установила NetBeans 8 + Tomcat 8

Проект не выполняется, пишет ошибку:

Код


Не удалось запустить Tomcat.
C:\NetBeansProject\testApp\nbproject\build-impl.xml:1045: Ошибка при развертывании: Не удалось запустить Tomcat.
Для получения подробных сведений см. протокол сервера.


Как с этим бороться?

Автор: mbasil 21.5.2015, 20:40
1. Проверьте переменную окружающей среды CATALINA_HOME, на какой из серверов она указывает (запускаться должен только один) . Переменную TOMCAT_HOME лучше не использовать, так как она работает только в Windows.

2 Обязательно должна быть установлена переменная JAVA_HOME. Если вы используете версию 8, то и JAVA_HOME должна указывать на JDK версии 8. При использовании Tomcat не устанавливайте JDK в директорию с пробелом, типа "Program Files"

3. В файле CATALINA_HOME/conf/server.xml должен использоваться порт, который свободен. По умолчанию он хочет 8080.

    <Connector port="8080" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true"/>

Проверьте - не занят ли порт или просто замените. Я обычно использую номер 8089

4. Для запуска сервера через его административную утилиту manager, NetBeans'у нужен администратор. В файле

CATALINA_HOME/conf/tomcatusers должна быть запись, похожая на:

<tomcat-users>
   <user name="admin" password="password" roles=" manager,script-manager" />
...
</tomcat-users>

5. При работе через NetBeans не запускайте сервер вручную, а перейдите на закладку Services, разверните узел Servers, найдите пиктограмму кота и щелкнув по ней правой кнопкой мыши выберите Start. Проверьте предварительно, чтобы Tomcat не был ранее стартован другими средствами. Там же можно в диалоговом окошке настроить свойства сервера. Посмотрите, какой там номер порта и при необходимости измените. 
Останавливайте тоже оттуда. 

Автор: azalia 22.5.2015, 01:09
Не получилось у меня подружиться с NetBeans. Все снесла, включая Tomcat 8.
Установила Eclipse и Tomcat 7.
Заработало...
Хотя тоже пришлось помучиться.

Автор: azalia 22.5.2015, 13:31
Не знаю, может я не совсем корректно задам вопрос, но мне не понятен один момент.
Почему при SAХ-парсинге в одном из примеров в параметре QNAME указывается не префикс, а имя тега? логичнее было бы там указывать префикс? 


Код

myHandler.startDocument();
myHandler.startElement(null, "contact", "contact", null);
....
myHandler.endDocument();

Автор: mbasil 22.5.2015, 14:29
Почему это логичнее? Элемент может быть любым из пространства имен, а префикс ведь придуман для создания уникального пространства имен, объединяющего набор элементов. 
То есть QNAME это квалифицированное имя элемента, как один префикс может сказать - какой из них?
Не забывайте тот факт, что мы имеем дело с методом обратного вызова (callback method)

Автор: azalia 22.5.2015, 15:04
Цитата(mbasil @  22.5.2015,  14:29 Найти цитируемый пост)
Элемент может быть любым из пространства имен, а префикс ведь придуман для создания уникального пространства имен, объединяющего набор элементов. 
То есть QNAME это квалифицированное имя элемента, как один префикс может сказать - какой из них?


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

 
myHandler.startElement(null, "contact", "с:contact", null);

При этом еще тогда первый null (namespaceURI) должен быть заполнен, типа:

http://adcd.com/abcd

и это будет соответствовать XML:

<с:contact xmlns:с="http://adcd.com/abcd">
  <c:name>Вася</c:name>
  <c:phone>12345</c:phone>
</c:contact>

Автор: mbasil 22.5.2015, 18:57
Префикс для Target Namespace можно опускать, поэтому то здесь Local Namt и Qualified Name совпадают, но если вы посмотрите документацию, то увидите, что в определенных ситуациях может быть опущено одно, или другое имя. 

Автор: azalia 22.5.2015, 20:20
спасибо за подсказку, похоже это надо просто потренироваться... у меня уже назрел другой вопрос smile

А как в сервлет вывести содержимое объекта типа xml на экран?

Каждый раз когда я пытаюсь обратиться .getString(), выдаются ошибки:
 
"Выполняется доступ к данным. Данные недоступны для этого столбца или параметра."

или

"Не удается считать данные из этого экземпляра, данные уже считаны"

Код

SQLXML xmlSource = rs.getSQLXML("Name");
SAXSource sxSource =  xmlSource.getSource(SAXSource.class);
XMLReader xmlReader = sxSource.getXMLReader();
xmlReader.setContentHandler(myHandler);
xmlReader.parse(sxSource.getInputSource());


Т.е. я так понимаю они уже прочитаны и распарсены (в консоли виден результат парсинга), а как теперь их вывести в браузер? или их надо предварительно куда-то еще записывать?

Если я буду делать все без всяких парсеров и просто обращаться к результирующему набору sql, то данные в браузер через .getString() выводятся, т.е. автоматически извлекаются из столбца типа xml в виде обычных строк текста (причем если смотреть получаемый код html, то там остается некоторая информация о тегах) и все.... это ведь нельзя назвать xml-данными?

Автор: mbasil 23.5.2015, 11:06
Все просто. Вы в своем обработчике, реализующем ContentHandler должны в методах startElement(), endElement() и characters() ПРИНЯТЬ данные, которые Вам засылает анализатор, я уже напоминал, что это callback методы. Кстати SAX подходит для обработки очень больших документов, структура которых полностью стабильна, так как надо много писать текста. Для небольших по размеру и относительно стабильных по структуре источников я предпочитаю JAXB, который был разработан для веб-сервисов и артефакты Java просто генерирует. В этом случае сложность не в написании програмы (как в SAX), а в том, чтобы разобраться с процессом генерирования и в сгенерированных классах.

Автор: azalia 23.5.2015, 19:07
А для меня как-то пока сложно smile

Код

public doGet{
// получаем параметры
String par = request.getParameter("parameter");

//вызываем нужный метод для его обработки, смотря что хотим делать с данными
transXML(par)

//чтобы отразить результат в браузере
PrintWriter out = response.getWriter();
out.println(..результат..+ res.getString())

}

public void transXML() {
// подключаемся к БД
// передаем параметр на обработку (пока не знаю как), получаем какой-то результат из БД
// обрабатываем результат, парсим
// записываем результат в какую-нибудь переменную res
// здесь же можем вывести результат через System.out.println, но он не отразится в браузере
// если пишем out.println, то не определена out, даже если ее определим, то потом ругается что нету response
}


Так наверно будет не совсем правильно, да?
Если реализовывать методы через обычные java-классы (в зависимости от целей обработки для каждого метода пусть будет отдельный java-класс), то снова вопрос как передать результат обработки в сервлет?
Или на каждую кнопку вызова (на клиенте) делать отдельный сервелет с отдельной функциональностью?
Под кнопкой вызова я подразумеваю, чтобы сначала нажималась кнопка "получить данные", потом когда получаешь данные давалась возможность изменить данные (добавить или удалить - 2 кнопки).

Надо сюда подключать еще работу с сессиями?

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

Автор: AntonSaburov 24.5.2015, 02:25
Настоятельно предлагаю все-таки для каждого вопроса открывать новый топик - может вам бы и другие помогли, но продираться сквозь все страницы и пытаться найти вопрос очень неудобно.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)