Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
根据Scala中的选项,如何添加XML标记?_Xml_Scala - Fatal编程技术网

根据Scala中的选项,如何添加XML标记?

根据Scala中的选项,如何添加XML标记?,xml,scala,Xml,Scala,与之相关,我想根据一个选项在Scala中添加一个XML标记 scala> def toXml(value1: String, value2: Option[String]) = | <body> | <tag1>{value1}</tag1> | {value2 map (x => <tag2>{x}</tag2>) flatten} | </body> toXml

与之相关,我想根据一个选项在Scala中添加一个XML标记

scala> def toXml(value1: String, value2: Option[String]) =
     | <body>
     |   <tag1>{value1}</tag1>
     |   {value2 map (x => <tag2>{x}</tag2>) flatten}
     | </body>
toXml: (value1: String,value2: Option[String])scala.xml.Elem
scala>def-toXml(value1:String,value2:Option[String])=
| 
|{value1}
|{value2映射(x=>{x})展平}
| 
toXml:(value1:String,value2:Option[String])scala.xml.Elem
如果该选项存在:

scala> toXml("value1", Some("value2"))
res1: scala.xml.Elem =
<body>
  <tag1>value1</tag1>
  <tag2>value2</tag2>
</body>
scala>toXml(“value1”,一些(“value2”))
res1:scala.xml.Elem=
价值1
价值2
如果该选项不存在:

scala> toXml("value1", None)
res2: scala.xml.Elem =
<body>
  <tag1>value1</tag1>

</body>
scala>toXml(“值1”,无)
res2:scala.xml.Elem=
价值1
我想根据一个选项生成很多标记,我想知道是否可以找到更简洁的解决方案。例如,使用?运算符,并像这样使用它(这是一个肮脏的解决方案,因为在调用?运算符之前,选项value2已转换为字符串):

scala>def-toXml2(值1:String,值2:Option[String])=
| 
|{value1}
|{{value2}?}
| 

有什么想法吗?

为什么不使用这样的if语句:

def toXml(value1:String,value2:Option[String]) =
  <body>
    <tag1>{value1}</tag1>
    {if (value2 isDefined) <tag2>{value2.get}</tag2>}
  </body>
implicit def optionElem(e: Elem) = new {
  def ? : NodeSeq = {
    require(e.child.length == 1)
    e.child.head match {
      case atom: Atom[Option[_]] => atom.data match {
        case None    => NodeSeq.Empty
        case Some(x) => e.copy(child = x match {
          case n: NodeSeq => n
          case x => new Atom(x)
        })
      }
      case _ => e
    }      
  }
}
def-toXml(value1:String,value2:Option[String])=
{value1}
{如果(value2已定义){value2.get}

这应该可以做到,并且是可以理解的,对吗?

您想要的
功能可以像这样实现:

def toXml(value1:String,value2:Option[String]) =
  <body>
    <tag1>{value1}</tag1>
    {if (value2 isDefined) <tag2>{value2.get}</tag2>}
  </body>
implicit def optionElem(e: Elem) = new {
  def ? : NodeSeq = {
    require(e.child.length == 1)
    e.child.head match {
      case atom: Atom[Option[_]] => atom.data match {
        case None    => NodeSeq.Empty
        case Some(x) => e.copy(child = x match {
          case n: NodeSeq => n
          case x => new Atom(x)
        })
      }
      case _ => e
    }      
  }
}
为简单起见,这仅适用于单子节点,以向您展示该概念(我想您应该能够从中编写更通用的函数,以备需要)

如果隐式函数在作用域中,则可以使用
运算符:

<body>
{ <tag1>{ Some("Hello") }</tag1>?  }
{ <tag2>{ None }</tag2>? }
{ <tag3>{ Some(<innerTag/>) }</tag3>? }
{ <tag4><innerTag/></tag4>? }
{ <tag5>{ None }</tag5>? }
</body>

{{Some(“Hello”)}?}
{{None}?}
{{Some()}?}
{ ? }
{{None}?}
将导致:

<body>
  <tag1>Hello</tag1>

  <tag3><innerTag></innerTag></tag3>
  <tag4><innerTag></innerTag></tag4>

</body>

你好

您还可以
折叠
选项:

{ value2.fold(NodeSeq.Empty)(x => <tag2>{x}</tag2>) }
{value2.fold(NodeSeq.Empty)(x=>{x}}

这里有一个简单的版本,它不使用折叠方法(可以说是误导性的,因为没有积累任何东西):

value2.map(x => <tag2>{x}</tag>).getOrElse(NodeSeq.Empty)
value2.map(x=>{x}).getOrElse(NodeSeq.Empty)

结果与佐尔坦的答案相同。

感谢安妮的回答,这更清楚地表明我对地图和平面的使用。然而,我希望避免为每个选项复制和粘贴isDefined测试。我正在寻找一种解决方案,其中代码看起来几乎像XML输出。这比其他答案简单得多。有没有办法避免空行?