2015-12-31 4 views
1

Я использую команду ниже, чтобы извлечь значение из поля «NAME». У меня есть результаты, но они нужны по-другому.Scala XML-анализ с помощью Xpath

mapVal.map(x => (x \\ "ALERT" \\"property" \\"name")text) 

sampleoutput: stackoverflowstackoverflowquery

Ожидаемые результаты: отдельные результаты в следующей строке

линия 1: Stackoverflow

линии 2: Stackoverflow

строка 3: запрос

Как я могу читать nodeseq один за другим?

+1

Было бы полезно, если бы вы предоставили XML, который производит эти результаты – philwalk

ответ

1

Если ваш XML структурирован как то, что я показываю здесь, последующий код делает то, что вы хотите:

import scala.language.postfixOps 
import scala.xml._ 
val xmlstr = 
""" 
<root> 
    <ALERT> 
    <property> 
     <name>stackoverflow</name> 
     <value>rox</value> 
    </property> 
    <property> 
     <name>stackoverflow</name> 
     <value></value> 
    </property> 
    <property> 
     <name>query</name> 
    </property> 
    </ALERT> 
</root> 
""" 
val mapVal = XML.loadString(xmlstr) 
val names = { 
    val alerts  = (mapVal \\ "ALERT") 
    val properties = (alerts \\"property") 
    (properties \\"name") 
} 
for(name <- names){ 
    printf("[%s]\n",name.text) 
} 

Вы можете использовать scala.xml литералы, но так как scala.xml устарела, вы можете рассмотрите возможность использования другой библиотеки xml.

Я экспериментировал с Yaidom в течение нескольких дней. Это активный проект по состоянию на месяц назад, в отличие от многих других альтернатив scala xml.

Другой вариант может быть RaptureXML, хотя я еще не нашел примеров использования.

Вот эквивалентный код с помощью yaidom:

import eu.cdevreeze.yaidom.simple.Elem 
val xmlstr = 
""" 
<root> 
    <ALERT> 
    <property> 
     <name>stackoverflow</name> 
     <value>rox</value> 
    </property> 
    <property> 
     <name>stackoverflow</name> 
     <value></value> 
    </property> 
    <property> 
     <name>query</name> 
    </property> 
    </ALERT> 
</root> 
""" 
val mapVal = fromString(xmlstr) 
val names = { 
    val alerts  = (mapVal \\ (_.localName == "ALERT")) 
    val properties = alerts.flatMap { a => (a \\ (_.localName == "property")) } 
    properties.flatMap { p => (p \\ (_.localName == "name")) } 
} 
for(name <- names){ 
    printf("[%s]\n",name.text) 
} 

def fromString(str:String) = { 
    import java.{ io => jio } 
    domParser.parse(new jio.ByteArrayInputStream(str.getBytes("utf-8"))).documentElement 
} 
import eu.cdevreeze.yaidom.parse.DocumentParserUsingDom 
lazy val domParser = DocumentParserUsingDom.newInstance 

Кстати, выше работает код, испытанные под Скале 2.11.7. Он также работает с 2.12.0-M3, используя библиотеку 2.11.7 scala.xml (он не гарантированно совместим с двоичными файлами, но, похоже, работает для этого примера).

Смежные вопросы