2009-08-05 3 views
4

У меня есть ответ XML что-то вроде этого -Java: XML Parser

<Response> <aa> <Fromhere> <a1>Content</a1> <a2>Content</a2> </Fromhere> </aa> </Response> 

Я хочу, чтобы извлечь все содержимое из <Fromhere> в </Fromhere> в строке. Можно ли это сделать через любую строковую функцию или через парсер XML?

Прошу совета.

ответ

4

Вы могли бы попробовать XPath подход к простоте в XML-парсинга:

InputStream response = new ByteArrayInputStream("<Response> <aa> " 
     + "<Fromhere> <a1>Content</a1> <a2>Content</a2> </Fromhere> " 
     + "</aa> </Response>".getBytes()); /* Or whatever. */ 

DocumentBuilder builder = DocumentBuilderFactory 
     .newInstance().newDocumentBuilder(); 
Document doc = builder.parse(response); 

XPath xpath = XPathFactory.newInstance().newXPath(); 
XPathExpression expr = xpath.compile("string(/Response/aa/FromHere)"); 
String result = (String)expr.evaluate(doc, XPathConstants.STRING); 

Следует заметить, что я не пробовал этот код , Может потребоваться настройка.

+0

Не будет ли это стирать элементы? – McDowell

+0

Кроме того, упаковка StringReader в StreamSource была бы более кодирующей-агностикой. – McDowell

+0

Спасибо @ izb.Это работало чудесно. Спасибо. – Pavan

2

Через синтаксический анализатор XML. Использование строковых функций для синтаксического анализа XML - это плохая идея ...
Помимо указаний Sun, указанных выше, вы можете проверить the DZone Refcardz on Java and XML, я нашел, что это было хорошее, краткое объяснение, как это сделать.
Но, скорее всего, на эту тему, вероятно, много веб-ресурсов, в том числе и на этом сайте.

+2

+1 для указания, что это плохая идея использовать «строковые функции для анализа XML». –

+0

DZone Refcardz выглядит интересно. Но серьезно: требуется полный адрес * и номер телефона * для регистрации на услугу «бесплатно»? –

0

Это должно работать

import java.util.regex.* 

Pattern p = Pattern.compile("<Fromhere>.*</Fromhere>"); 
Matcher m = p.matcher(responseString); 
String whatYouWant = m.group(); 

Было бы немного более многословным использовать сканер, но это может работать тоже.

ли это хорошая идея для кого-то более опытного, чем я

+0

Привет, комментарий был неполным. Не могу ничего увидеть после «работы:» – Pavan

+0

Извините, нажмите enter слишком рано. –

+0

Пока эти разделители не отображаются в комментарии или CDATA или что-то в этом роде ... – McDowell

2

Вы можете применить таблицу стилей XSLT для извлечения желаемого содержимого.

Эта таблица стилей должна соответствовать вашему примеру:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/Response/aa/Fromhere/*"> 
     <xsl:copy> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

Примените это что-то вроде следующего (обработка исключений не входит):

String xml = "<Response> <aa> <Fromhere> <a1>Content</a1> <a2>Content</a2> </Fromhere> </aa> </Response>"; 
Source xsl = new StreamSource(new FileReader("/path/to/file.xsl"); 

TransformerFactory transformerFactory = TransformerFactory.newInstance(); 
Transformer transformer = transformerFactory.newTransformer(xsl); 
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 

StringWriter out = new StringWriter(); 
transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(out)); 

System.out.println(out.toString()); 

Это должно работать с любой версией Java, начиная с 1.4 ,

+0

Возможно, вы захотите установить OutputKeys.OMIT_XML_DECLARATION = «да» на трансформаторе. – McDowell

+0

На самом деле я использовал метод html в xsl для подавления объявления xml, но ваше предложение стало лучше. Я включил его в ответ, спасибо. –

0

Одним из вариантов является использование StreamFilter:

class MyFilter implements StreamFilter { 
    private boolean on; 

    @Override 
    public boolean accept(XMLStreamReader reader) { 
    final String element = "Fromhere"; 
    if (reader.isStartElement() && element.equals(reader.getLocalName())) { 
     on = true; 
    } else if (reader.isEndElement() 
     && element.equals(reader.getLocalName())) { 
     on = false; 
     return true; 
    } 
    return on; 
    } 
} 

В сочетании с Transformer, вы можете использовать это, чтобы безопасно разобрать логически эквивалентную разметку так:

<Response> 
    <!-- <Fromhere></Fromhere> --> 
    <aa> 
    <Fromhere> 
     <a1>Content</a1> <a2>Content</a2> 
    </Fromhere> 
    </aa> 
</Response> 

Демо:

StringWriter writer = new StringWriter(); 

XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
XMLStreamReader reader = inputFactory 
    .createXMLStreamReader(new StringReader(xmlString)); 
reader = inputFactory.createFilteredReader(reader, new MyFilter()); 
TransformerFactory transFactory = TransformerFactory.newInstance(); 
Transformer transformer = transFactory.newTransformer(); 
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
transformer.transform(new StAXSource(reader), new StreamResult(writer)); 

System.out.println(writer.toString()); 

Это программный вариант на Massimiliano Fliri's подход.