Разбор XML-тегов с возвратом каретки в тексте

Я пытаюсь проанализировать файл XML с большим текстом внутри тегов. Иногда в текстах есть возврат каретки. Когда я отлаживаю, моя строка перезаписывается с возвратом каретки ("\n"), что иногда приводит к пустой строке или строке с одной строкой.

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

Пример XML-файла:

<?xml version="1.0" encoding="utf-8" ?> 
<vacaturedetails>
<details>
<titel>MEDEWERKER VOOR ONDERHOUDSDIENST</titel> 
<werkveld>METAALMECHANICA</werkveld> 
<regio>Regio Roeselare- Izegem</regio> 
<tewerkstellingsplaats>Bedrijf in Roeselare met goeie reputatie.</tewerkstellingsplaats> 
<diploma1>A2 (Beroeps + 7ej, Technisch, ASO)</diploma1> 
<diploma2>A3 (Beroeps tot 6e j, Deeltijds, Leercontract)</diploma2> 
<taal1>Nederlands</taal1> 
<ervaring>6 maand - 2 jaar</ervaring> 
<rijbewijs>B</rijbewijs> 
<rijbewijsOmsch>Auto</rijbewijsOmsch> 
<omschrijving>- Inzicht in, en zelfstandig kunnen monteren en lassen van metalen constructies. - Hulp bij het ontwikkelen van nieuwe constructies van onderdelen in de productielijn of verbeteren van bestaande constructies. - Kunnen rijden met heftruck en werken met hoogtewerker. - Plaatsen van leidingen voor perslucht, water, ...en sanitair. - Kleine herstellingen uitvoeren. - Hulp bij verhuis binnen het bedrijf. - Allerhande klusjes die nodig zijn aan en rond de bedrijfsgebouwen. </omschrijving> 
<aanbod>Dagwerk met een goeie verloning in een goei werksfeer. Optie vast na uitzendperiode.    </aanbod> 
<profiel>- Kunnen lassen met halfautomaat, kennis autogeen lassen is een pluspunt. - Kunnen rijden met heftruck (attest is een pluspunt) en werken met hoogtewerker. - Inzicht hebben en zelfstandig kunnen monteren van constructies. - Kennis van sanitair (water, gas, perslucht) - Ervaring is een must!</profiel> 
</details>
</vacaturedetails>

Вот как выглядит мой парсер:

package stage.accent.webservice;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import stage.accent.domain.VacatureDetails;

public class vacatureDetailsWebservice extends DefaultHandler {

private boolean vacaturedetailstag = false;
private boolean detailstag = false;
private boolean titeltag = false;
private boolean werkveldtag = false;
private boolean tewerkstellingsplaatstag = false;
private boolean diploma1tag = false;
private boolean diploma2tag = false;
private boolean taal1tag = false;
private boolean taal2tag = false;
private boolean taal3tag = false;
private boolean taal4tag = false;
private boolean taal5tag = false;
private boolean ervaringtag = false;
private boolean omschrijvingtag = false;
private boolean aanbodtag = false;
private boolean profieltag = false;
private boolean rijbewijstag = false;
private boolean rijbewijsOmschtag = false;

private String test;


//private Vacature vacature = new Vacature();
private VacatureDetails details;

public VacatureDetails getVacatures() {
    return this.details;

}

@Override
public void startDocument() throws SAXException {

    this.details = new VacatureDetails();
}

@Override
public void endDocument() throws SAXException {
    // Nothing to do
}

/** Gets be called on opening tags like: 
 * <tag> 
 * Can provide attribute(s), when xml was like:
 * <tag attribute="attributeValue">*/
@Override
public void startElement(String namespaceURI, String localName,
        String qName, Attributes atts) throws SAXException {
    if (localName.equals("vacaturedetails")) {
        this.vacaturedetailstag = true;             
    }else if (localName.equals("details")) {
        this.detailstag = true;
    }else if (localName.equals("titel")) {
        this.titeltag = true;
    }else if (localName.equals("werkveld")){
        this.werkveldtag = true;
    }else if (localName.equals("tewerkstellingsplaats")){
        this.tewerkstellingsplaatstag = true;
    }else if (localName.equals("diploma1")){
        this.diploma1tag = true;
    }else if (localName.equals("diploma2")){
        this.diploma2tag = true;
    }else if (localName.equals("taal1")){
        this.taal1tag = true;
    }else if (localName.equals("taal2")){
        this.taal2tag = true;
    }else if (localName.equals("taal3")){
        this.taal3tag = true;
    }else if (localName.equals("taal4")){
        this.taal4tag = true;
    }else if (localName.equals("taal5")){
        this.taal5tag = true;
    }else if (localName.equals("ervaring")){
        this.ervaringtag = true;
    }else if (localName.equals("rijbewijs")){
        this.rijbewijstag = true;
    }else if (localName.equals("rijbewijsOmsch")){
        this.rijbewijsOmschtag = true;
    }else if (localName.equals("omschrijving")){
        this.omschrijvingtag = true;
    }else if (localName.equals("aanbod")){
        this.aanbodtag = true;
    }else if (localName.equals("profiel")){
        this.profieltag = true;
    }
}

/** Gets be called on closing tags like: 
 * </tag> */
@Override
public void endElement(String namespaceURI, String localName, String qName)
        throws SAXException {
    if (localName.equals("vacaturedetails")) {
        this.vacaturedetailstag = false;
    }else if (localName.equals("details")) {
        this.detailstag = false;
    }else if (localName.equals("titel")) {
        this.titeltag = false;
    }else if (localName.equals("werkveld")){
        this.werkveldtag = false;
    }else if (localName.equals("tewerkstellingsplaats")){
        this.tewerkstellingsplaatstag = false;
    }else if (localName.equals("diploma1")){
        this.diploma1tag = false;
    }else if (localName.equals("diploma2")){
        this.diploma2tag = false;
    }else if (localName.equals("taal1")){
        this.taal1tag = false;
    }else if (localName.equals("taal2")){
        this.taal2tag = false;
    }else if (localName.equals("taal3")){
        this.taal3tag = false;
    }else if (localName.equals("taal4")){
        this.taal4tag = false;
    }else if (localName.equals("taal5")){
        this.taal5tag = false;
    }else if (localName.equals("ervaring")){
        this.ervaringtag = false;
    }else if (localName.equals("rijbewijs")){
        this.rijbewijstag = false;
    }else if (localName.equals("rijbewijsOmsch")){
        this.rijbewijsOmschtag = false;
    }else if (localName.equals("omschrijving")){
        this.omschrijvingtag = false;
    }else if (localName.equals("aanbod")){
        this.aanbodtag = false;
    }else if (localName.equals("profiel")){
        this.profieltag = false;
    }
}

/** Gets be called on the following structure: 
 * <tag>characters</tag> */
@Override
public void characters(char ch[], int start, int length) {
    if(this.titeltag){
        details.setTitel(new String(ch, start, length));
    }
    if(this.werkveldtag){
        details.setWerkveld(new String(ch, start, length));
    }
    if(this.tewerkstellingsplaatstag){
        details.setTewerkstellingsplaats(new String(ch, start, length));

    }
    if(this.diploma1tag){
        details.setDiploma1(new String(ch, start, length));
    }
    if(this.diploma2tag){
        details.setDiploma2(new String(ch, start, length));
    }
    if(this.taal1tag){
        details.setTaal1(new String(ch, start, length));
    }
    if(this.taal2tag){
        details.setTaal2(new String(ch, start, length));
    }
    if(this.taal3tag){
        details.setTaal3(new String(ch, start, length));
    }
    if(this.taal4tag){
        details.setTaal4(new String(ch, start, length));
    }
    if(this.taal5tag){
        details.setTaal5(new String(ch, start, length));
    }
    if(this.ervaringtag){
        details.setErvaring(new String(ch, start, length));
    }
    if(this.rijbewijstag){
        details.setRijbewijs(new String(ch, start, length));
    }
    if(this.rijbewijsOmschtag){
        details.setRijbewijsOmsch(new String(ch, start, length));
    }           
    if(this.omschrijvingtag){
        details.setOmschrijving(new String(ch, start, length));
    }
    if(this.aanbodtag){
        details.setAanbod(new String(ch, start, length));
    }
    if(this.profieltag){
        details.setProfiel(new String(ch, start, length));
    }
    test = details.toString();
}

}

Вывод этого примера omschrijving был = - Allerhande klusjes die nodig zijn aan en rond de bedrijfsgebouwen.

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


person Hannelore    schedule 18.04.2011    source источник


Ответы (2)


Я понимаю, что вы всегда перезаписываете значение этого тега последним фрагментом. Замените этот кусок кода в методе characters

if(this.omschrijvingtag){
    details.setOmschrijving(new String(ch, start, length));
}

с участием

if(this.omschrijvingtag){
    details.setOmschrijving((details.getOmschrijving() != null? details.getOmschrijving() : "") + new String(ch, start, length));
}

РЕДАКТИРОВАТЬ: в основном, вы проверяете, установлено ли значение Omschrijving или нет, и действуете соответственно. В случае, если этот код смущает вас, проверьте то же самое, но немного другое выражение

if(this.omschrijvingtag){
    if(details.getOmschrijving() != null) {
        details.setOmschrijving(details.getOmschrijving() + new String(ch, start, length));
    }
    else {
        details.setOmschrijving(new String(ch, start, length));
    }
}

Таким образом, вы проверяете, является ли значение Omschrijving пустым, и если это не так, вы объединяете уже существующее значение, в противном случае вы просто присваиваете новое значение. Вот и все.

person Ilya Saunkin    schedule 18.04.2011
comment
Большое тебе спасибо! Это работало как шарм, но, к сожалению, я всего лишь очень простой программист и не совсем понимаю код. Хотите поделиться со мной? Большое тебе спасибо! - person Hannelore; 18.04.2011
comment
Нет проблем, чувак. Проверьте редактирование, я добавил некоторые пояснения. - person Ilya Saunkin; 18.04.2011

Я совершенно уверен, что возврат каретки недействителен во многих анализаторах XML. вам нужно заключить большие текстовые значения в CData, см. здесь

т.е. попробуйте что-то подобное, если вы можете изменить XML.

<root>
  <child>
  <![CDATA[
    Text you want to escape goes here...
  ]]>
  </child>
</root>

Если вы не можете изменить xml, вам нужно будет выполнить замену поиска в строке перед синтаксическим анализом.

Надеюсь, это поможет

РЕДАКТИРОВАТЬ: просто перечитайте свой пост. Я предполагаю, что вы не можете изменить XML? В этом случае вы должны прочитать XML-сохранение в строку и найти/заменить любой "\n" перед передачей строки в ваш парсер SAX. мой ноутбук на работе, поэтому не могу поделиться кодом, где я это сделал. Если вы все еще не решили это к завтрашнему дню, я могу поделиться с вами кодом...

person wired00    schedule 18.04.2011
comment
Спасибо за быстрый ответ! Поскольку я не могу изменить XML, решение CDATA мне не подходит. Я попробовал код @Elijah Saounkine, который также ответил, и это сработало! Я думаю, что его код - лучшее решение, потому что возврат каретки все еще нужно отображать в выводе. - person Hannelore; 18.04.2011
comment
Спасибо, это сработало для меня. Интересно, что если ввести ]]› в середине текста, это может испортить xml-документ, поэтому нужно проверить, что в тексте нет ]]›, верно? - person Lumis; 05.01.2013
comment
@Lumis хм, да, если в вашем тексте есть ]]>, это будет проблемой. Можете ли вы очистить текст при сохранении в базе данных или при извлечении при построении XML или это вне вашего контроля? Вам просто нужно выполнить поиск/заменить в полях TEXT, которые вам нужно окружить тегами CDATA - person wired00; 07.01.2013
comment
Да, когда текст отправляется формой, я просто запускаю myText = myText.replace(]]›, ), прежде чем использовать его или сохранить в XML. Маловероятно, что кто-нибудь наберет это в моем приложении, но лучше перестраховаться. - person Lumis; 07.01.2013