如何迭代可以具有可选属性的XML元素?

时间:2012-01-13 00:23:01

标签: scala xml-parsing

我尝试迭代XML文件以获取特定类型<Card>的所有元素。此类型还可以具有可选的属性。

XML示例:

<Lesson>
  <Description>Description</Description>
  <Card learnedTimestamp="1234567", isRepeatedByTyping="true", batch="5">
      <FrontSide>Foo1</FrontSide>
      <ReverseSide>Bar1</ReverseSide>
      <InformationLine>Info1</InformationLine>
  </Card>
  <Card>
      <FrontSide>Foo2</FrontSide>
      <ReverseSide>Bar2</ReverseSide>
      <InformationLine>Info2</InformationLine>
  </Card>
</Lesson>

Scala代码:

    class XMLParser(fqFileName: String) {
      val pauDoc: Elem = XML.loadFile(fqFileName)
      def printXMLFile() = {
        var cardCount = 0
        val lesson = (pauDoc \\ "Lesson")    
        for(val card <- lesson \\ "Card"){      
          cardCount = cardCount + 1
          println("Card No " + cardCount)
          val frontSide = (card \\ "FrontSide").text
          println("FrontSide Value: " + frontSide)      
          val reverseSide = (card \\ "ReverseSide").text
          println("ReverseSide Value.text: " + reverseSide)      
          val infoLine = (card \\ "InformationLine").text
          println("InformationLine Value: " + infoLine)      
        }    
      }
    }

但是,只有<Card>元素没有任何属性时,此代码才有效。有没有人知道我如何处理属性,特别是如果它们是可选的?

P.S。:这是我得到的例外。

    Exception in thread "main" org.xml.sax.SAXParseException: Element type "Card" must be followed by either attribute specifications, ">" or "/>".
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.seekCloseOfStartTag(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
        at javax.xml.parsers.SAXParser.parse(Unknown Source)
        at scala.xml.factory.XMLLoader$class.loadXML(XMLLoader.scala:40)
        at scala.xml.XML$.loadXML(XML.scala:40)
        at scala.xml.factory.XMLLoader$class.loadFile(XMLLoader.scala:49)
        at scala.xml.XML$.loadFile(XML.scala:40)
        at de.htwg_konstanz.ecardman.common.XMLParser.<init>(XMLParser.scala:7)
        at de.htwg_konstanz.ecardman.common.XMLParserMain$.main(XMLParserMain.scala:23)
        at de.htwg_konstanz.ecardman.common.XMLParserMain.main(XMLParserMain.scala)

1 个答案:

答案 0 :(得分:2)

这适用于2.9.1:

val raw = """<Lesson>
  <Description>Description</Description>
  <Card learnedTimestamp="1234567" isRepeatedByTyping="true" batch="5">
      <FrontSide>Foo1</FrontSide>
      <ReverseSide>Bar1</ReverseSide>
      <InformationLine>Info1</InformationLine>
  </Card>
  <Card>
      <FrontSide>Foo2</FrontSide>
      <ReverseSide>Bar2</ReverseSide>
      <InformationLine>Info2</InformationLine>
  </Card>
</Lesson>"""

class XMLParser(fqFileName: String) {
  import xml._
  val pauDoc: Elem = XML.loadString(fqFileName)
  def printXMLFile() = {
    var cardCount = 0
    val lesson = (pauDoc \\ "Lesson")    
    for(card <- lesson \\ "Card"){      
      cardCount = cardCount + 1
      println("Card No " + cardCount)
      val frontSide = (card \\ "FrontSide").text
      println("FrontSide Value: " + frontSide)      
      val reverseSide = (card \\ "ReverseSide").text
      println("ReverseSide Value.text: " + reverseSide)      
      val infoLine = (card \\ "InformationLine").text
      println("InformationLine Value: " + infoLine)      
    }    
  }
}

new XMLParser(raw).printXMLFile()

打印:

Card No 1
FrontSide Value: Foo1
ReverseSide Value.text: Bar1
InformationLine Value: Info1
Card No 2
FrontSide Value: Foo2
ReverseSide Value.text: Bar2
InformationLine Value: Info2

这不是你所期望的吗?我刚用loadString代替loadFile,但这只是用于测试。