Scala, как получить тег XML с необязательным атрибутом - PullRequest
3 голосов
/ 10 апреля 2019

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

У меня есть этот вход:

<substance-classes>
    <nucleic-acid-sequence display-name="Nucleic Acid Sequence">
        <nucleic-acid-base>
            <base-symbol>a</base-symbol>
            <count>295</count>
        </nucleic-acid-base>
        <nucleic-acid-base>
            <base-symbol>c</base-symbol>
            <count>329</count>
        </nucleic-acid-base>
        <nucleic-acid-base>
            <base-symbol>g</base-symbol>
            <count>334</count>
        </nucleic-acid-base>
        <nucleic-acid-base>
            <base-symbol>t</base-symbol>
            <count>268</count>
        </nucleic-acid-base>
    </nucleic-acid-sequence>
    <genbank-information>
        <genbank-accession-number>EU186063</genbank-accession-number>
    </genbank-information>
</substance-classes>

Я пытаюсь заменить содержимое <nucleic-acid-sequence> этим

val newNucleicAcidSequenceNode = <nucleic-acid-sequence>{ myfunction 
} </nucleic-acid-sequence>

Но некоторые <nucleic-acid-sequence> имеют такие атрибуты, как <nucleic-acid- sequence display-name="Nucleic Acid Sequence">. Так как мой newNucleicAcidSequenceNode - это жестко закодированный тег, который я теряю.

Как сохранить необязательные атрибуты и передать { myfunction } <nucleic-acid-sequence> тег?

1 Ответ

1 голос
/ 10 апреля 2019

Итак, если я вас хорошо понял:

  • вы хотите заменить только часть вашего xml
  • , эта часть - дети любого nucleic-acid-sequence в substance-classes
  • вы не хотите терять какие-либо атрибуты любого из указанных выше nucleic-acid-sequence
  • изменение этих вышеупомянутых потомков выполняется функцией (myFunction)

Таким образом, мой ответ будет в таком случае:

import scala.xml.{Node, Elem}

val myXml: Elem =
      <substance-classes>
        <nucleic-acid-sequence display-name="Nucleic Acid Sequence">
          <nucleic-acid-base>
            <base-symbol>a</base-symbol>
            <count>295</count>
          </nucleic-acid-base>
          <nucleic-acid-base>
            <base-symbol>c</base-symbol>
            <count>329</count>
          </nucleic-acid-base>
          <nucleic-acid-base>
            <base-symbol>g</base-symbol>
            <count>334</count>
          </nucleic-acid-base>
          <nucleic-acid-base>
            <base-symbol>t</base-symbol>
            <count>268</count>
          </nucleic-acid-base>
        </nucleic-acid-sequence>
        <genbank-information>
          <genbank-accession-number>EU186063</genbank-accession-number>
        </genbank-information>
      </substance-classes>

def myFunction(children: Seq[Node]) : Seq[Node] = ??? // whatever you want it to be

// Here's the replacement:

myXml.copy(child = myXml.child.map {
  case e@Elem(_, "nucleic-acid-sequence", _, _, children@_*) =>
    e.asInstanceOf[Elem].copy(child = myFunction(children))
  case other => other
})

Например, myFunction может содержать только детей, число которых превышает 300 и может быть что-то вроде:

import scala.util.{ Try, Success }
def myFunction(children: Seq[Node]): Seq[Node] = children.collect {
  case e: Node if Try((e \ "count").text.toInt > 300) == Success(true) =>
  e
}

В этом случае, если вы замените нереализованный myFunction в первом фрагменте на это, замена даст:

  <substance-classes>
    <nucleic-acid-sequence display-name="Nucleic Acid Sequence"><nucleic-acid-base>
        <base-symbol>c</base-symbol>
        <count>329</count>
      </nucleic-acid-base><nucleic-acid-base>
        <base-symbol>g</base-symbol>
        <count>334</count>
      </nucleic-acid-base></nucleic-acid-sequence>
    <genbank-information>
      <genbank-accession-number>EU186063</genbank-accession-number>
    </genbank-information>
  </substance-classes>

Как вы видите, ни один атрибут nucleic-acid-sequence не потерян и ваша функция сохраниласьдва узла над четырьмя для определенного условия.

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

...