[SCALA] 스칼라 - XML에 중첩 된 요소를 수정
SCALA스칼라 - XML에 중첩 된 요소를 수정
나는 스칼라을 배우고, 나는 일부 XML에서 중첩 된 노드를 업데이트 할 찾고 있어요. 나는 뭔가 작업을 가지고 있지만 가장 우아한 방법이 있는지 궁금 해요.
좀 XML을 가지고 :
val InputXml : Node =
<root>
<subnode>
<version>1</version>
</subnode>
<contents>
<version>1</version>
</contents>
</root>
그리고 난 버전 하위 노드에서 노드가 아니라 내용의 하나를 업데이트하고 싶습니다.
여기 내 기능은 다음과 같습니다
def updateVersion( node : Node ) : Node =
{
def updateElements( seq : Seq[Node]) : Seq[Node] =
{
var subElements = for( subNode <- seq ) yield
{
updateVersion( subNode )
}
subElements
}
node match
{
case <root>{ ch @ _* }</root> =>
{
<root>{ updateElements( ch ) }</root>
}
case <subnode>{ ch @ _* }</subnode> =>
{
<subnode>{ updateElements( ch ) }</subnode>
}
case <version>{ contents }</version> =>
{
<version>2</version>
}
case other @ _ =>
{
other
}
}
}
이 기능을 작성하는 좀 더 간결한 방법이 있나요?
해결법
-
==============================
1.나는 원래 논리가 좋은 생각합니다. 이것은 (? 내가 말을 감히된다)보다 스칼라 틱 맛을 가진 동일한 코드입니다 :
나는 원래 논리가 좋은 생각합니다. 이것은 (? 내가 말을 감히된다)보다 스칼라 틱 맛을 가진 동일한 코드입니다 :
def updateVersion( node : Node ) : Node = { def updateElements( seq : Seq[Node]) : Seq[Node] = for( subNode <- seq ) yield updateVersion( subNode ) node match { case <root>{ ch @ _* }</root> => <root>{ updateElements( ch ) }</root> case <subnode>{ ch @ _* }</subnode> => <subnode>{ updateElements( ch ) }</subnode> case <version>{ contents }</version> => <version>2</version> case other @ _ => other } }
그것은 (:) 실제로 동일) 더 컴팩트 보인다
당신이 원한다면, 당신은 너무 updateElements의 제거 얻을 수 있습니다. 당신은 순서의 모든 요소에 updateVersion을 적용 할. 즉,지도 방법입니다. 그것으로, 당신은 선을 다시 작성할 수 있습니다
case <subnode>{ ch @ _* }</subnode> => <subnode>{ updateElements( ch ) }</subnode>
와
case <subnode>{ ch @ _* }</subnode> => <subnode>{ ch.map(updateVersion (_)) }</subnode>
업데이트 버전은 1 매개 변수를 사용하는 것처럼 나는 99 %는 당신이 그것을 및 쓰기를 생략 할 수있어 :
case <subnode>{ ch @ _* }</subnode> => <subnode>{ ch.map(updateVersion) }</subnode>
로 끝 :
def updateVersion( node : Node ) : Node = node match { case <root>{ ch @ _* }</root> => <root>{ ch.map(updateVersion )}</root> case <subnode>{ ch @ _* }</subnode> => <subnode>{ ch.map(updateVersion ) }</subnode> case <version>{ contents }</version> => <version>2</version> case other @ _ => other }
어떻게 생각해?
-
==============================
2.이 모든 시간은 아무도 실제로 가장 적절한 답을주지 않았다! 지금은 그것을 배운 것을,하지만 여기에 나의 새로운 걸릴입니다 :
이 모든 시간은 아무도 실제로 가장 적절한 답을주지 않았다! 지금은 그것을 배운 것을,하지만 여기에 나의 새로운 걸릴입니다 :
import scala.xml._ import scala.xml.transform._ object t1 extends RewriteRule { override def transform(n: Node): Seq[Node] = n match { case Elem(prefix, "version", attribs, scope, _*) => Elem(prefix, "version", attribs, scope, Text("2")) case other => other } } object rt1 extends RuleTransformer(t1) object t2 extends RewriteRule { override def transform(n: Node): Seq[Node] = n match { case sn @ Elem(_, "subnode", _, _, _*) => rt1(sn) case other => other } } object rt2 extends RuleTransformer(t2) rt2(InputXml)
이제 몇 가지 설명합니다. 클래스 RewriteRule의 추상이다. 그것은 모두 변환이라는 두 가지 방법을 정의합니다. 그 중 하나는 단일 노드, 노드의 다른 시퀀스를합니다. 그것은 우리가 직접 인스턴스화 할 수 없습니다, 추상 클래스입니다. transformmethods이 경우 재정의 하나에, 정의를 추가함으로써, 우리는 그것의 익명의 하위 클래스를 만들 수 있습니다. 그것은 많은 작업을 수행 할 수 있지만 각 RewriteRule의 요구는 단일 작업 자체를 우려.
다음에, 클래스 RuleTransformer 파라미터로 RewriteRule의 가변 개수 걸린다. 이 방법은 노드 소요 변환 및 각과를 인스턴스화하는 데 사용되는 모든 RewriteRule의를 적용하여, 노드의 순서를 반환합니다.
두 클래스는 하나 개의 필요가 더 높은 수준에서 자신을 염려하지있는 몇 가지 방법을 정의 BasicTransformer에서 파생. 그것은 RuleTransformer와 RewriteRule의 모두가 그와 관련된 문법 설탕을 사용할 수 있도록 메서드 호출은,하지만, 변환을 적용합니다. 예에서, 전자는 않고, 나중에하지 않습니다.
첫 번째 상위 레벨 노드에 필터를 적용하고, 두 번째 필터를 통과 무엇에 변경 사항을 적용 할 때 여기에서 우리는, RuleTransformer의 두 가지 수준을 사용합니다.
추출기 Elem 모델은 그래서 같은 공간이나 속성 여부가 있는지 세부 자신 우려 할 필요가 없다는 것을 사용한다. 아니 요소 버전의 내용이 완전히 삭제하고 필요한 경우 그것은, 너무 대해 일치 할 수 있습니다 (2)로 대체된다.
_ 추출기의 마지막 매개 변수가 _ * 있음도 참고하지. 즉, 이러한 요소들은 여러 아이를 가질 수 있습니다. 당신이 *를 잊어 버린 경우, 경기는 실패 할 수 있습니다. 어떤 공백이 없다면 예에서, 경기는 실패하지 않을 것입니다. 공백은 텍스트 요소로 변환되기 때문에, 하위 노드에서 하나의 공백이 실패하는 경기를 구분합니다.
이 코드는 제시 한 다른 제안보다 큰,하지만 다른 사람보다 XML의 구조 훨씬 적은 지식을 가지고있는 장점이있다. 얼마나 많은 수준에 상관없이 - - 하위 노드라는 요소에 상관없이 네임 스페이스, 속성 등은 다음과 같습니다 버전이라는 모든 요소를 변경
당신이 할 수있는 많은 변형이있는 경우 또한 ... 음, 재귀 패턴 매칭 빠르게 탄력성이된다. RewriteRule의 및 RuleTransformer를 사용하면 효과적으로 스칼라 코드 파일을 XSLT 대체 할 수 있습니다.
-
==============================
3.당신은 리프트의 CSS 선택기 변환 및 쓰기를 사용할 수 있습니다 :
당신은 리프트의 CSS 선택기 변환 및 쓰기를 사용할 수 있습니다 :
"subnode" #> ("version *" #> 2)
http://stable.simply.liftweb.net/#sec:CSS-Selector-Transforms 참조
-
==============================
4.나는 이래 배운 내가 다른 답변에서 우수한 솔루션으로 간주 할 것을 제시 하였다. 나는 내가 하위 노드 제한에 대한 계정에 실패했다 눈치 나는 또한이 일을 해결했습니다.
나는 이래 배운 내가 다른 답변에서 우수한 솔루션으로 간주 할 것을 제시 하였다. 나는 내가 하위 노드 제한에 대한 계정에 실패했다 눈치 나는 또한이 일을 해결했습니다.
질문 주셔서 감사합니다! XML을 처리 할 때 난 그냥 멋진 물건을 배웠다. 여기에 당신이 원하는 것입니다 :
def updateVersion(node: Node): Node = { def updateNodes(ns: Seq[Node], mayChange: Boolean): Seq[Node] = for(subnode <- ns) yield subnode match { case <version>{ _ }</version> if mayChange => <version>2</version> case Elem(prefix, "subnode", attribs, scope, children @ _*) => Elem(prefix, "subnode", attribs, scope, updateNodes(children, true) : _*) case Elem(prefix, label, attribs, scope, children @ _*) => Elem(prefix, label, attribs, scope, updateNodes(children, mayChange) : _*) case other => other // preserve text } updateNodes(node.theSeq, false)(0) }
이제 설명. 처음이자 마지막의 경우 문은 명백해야한다. 마지막 하나의 요소가 아니다는 XML의 그 부분을 잡기 위해 존재한다. 또는, 즉, 텍스트입니다. 첫 번째 문에 참고하지만, 플래그에 대한 테스트 버전이 변경되거나되지 않을 수 있는지 여부를 나타냅니다.
두 번째와 세 번째의 경우 문은 객체 Elem 모델에 대해 패턴 매처를 사용합니다. 이 모든 구성 요소 부분으로 요소를 중단합니다. 마지막 매개 변수, "아이들은 @ _ *"아무것도의 목록에 아이를 일치합니다. 또는보다 구체적으로는, 서열 [노드]. 그렇다면 우리는 추출 된 부품, 소자를 재구성하지만 순환 공정 하 updateNodes에 서열 [노드]를 통과한다. 우리는 요소의 하위 노드에 일치하는 경우, 우리는 버전의 변화를 가능하게 true로 플래그 mayChange을 변경합니다.
마지막 줄에서, 우리는 node.theSeq 서열을 생성하기 위해 사용 [노드] 노드 및 (0)에서 서열의 첫 번째 요소를 얻을 [노드] 결과로 반환. updateNodes이 (위해 ... 수율지도로 번역) 본질적으로지도 기능을하기 때문에, 우리는 결과가 하나 개의 요소 만이 알고 있습니다. 우리는 하위 노드 요소는 조상하지 않는 한 버전이 변경되지 않음을 보장하기 위해 거짓 깃발을 전달합니다.
그 일을 약간 다른 방법은 더 강력하지만 좀 더 자세한하고, 모호한 것이있다 :
def updateVersion(node: Node): Node = { def updateNodes(ns: Seq[Node], mayChange: Boolean): Seq[Node] = for(subnode <- ns) yield subnode match { case Elem(prefix, "version", attribs, scope, Text(_)) if mayChange => Elem(prefix, "version", attribs, scope, Text("2")) case Elem(prefix, "subnode", attribs, scope, children @ _*) => Elem(prefix, "subnode", attribs, scope, updateNodes(children, true) : _*) case Elem(prefix, label, attribs, scope, children @ _*) => Elem(prefix, label, attribs, scope, updateNodes(children, mayChange) : _*) case other => other // preserve text } updateNodes(node.theSeq, false)(0) }
이 버전은 당신이 어떤 "버전"태그, 무엇이든 그것의 접두사, attribs 및 범위를 변경할 수 있습니다.
-
==============================
5.저울 XML은 "대신에"편집 도구를 제공합니다. 물론 그 모든 불변 그러나 여기 스케일의 솔루션입니다 :
저울 XML은 "대신에"편집 도구를 제공합니다. 물론 그 모든 불변 그러나 여기 스케일의 솔루션입니다 :
val subnodes = top(xml).\*("subnode"l).\*("version"l) val folded = foldPositions( subnodes )( p => Replace( p.tree ~> "2"))
구문처럼의 XPath는 저울의 서명 기능, 그것은 네임 스페이스 (로컬 이름 만)이 없어야 문자열 지정 후 리터입니다.
다시 함께 결합 결과 얻어진 소자 및 그 변형을 통해 foldPositions 반복.
-
==============================
6.한 가지 방법은 렌즈 것 (예를 들어 scalaz의). 아주 명확 프레젠테이션 http://arosien.github.io/scalaz-base-talk-201208/#slide35를 참조하십시오.
한 가지 방법은 렌즈 것 (예를 들어 scalaz의). 아주 명확 프레젠테이션 http://arosien.github.io/scalaz-base-talk-201208/#slide35를 참조하십시오.
-
==============================
7.https://github.com/geirolz/advxml :이 프로젝트를 확인
https://github.com/geirolz/advxml :이 프로젝트를 확인
그것은 XML 변환 및 직렬화를 단순화하기위한 목적으로 RuleTransformer (표준 스칼라 XML 라이브러리)와 고양이를 기반으로 간단한 라이브러리이다.
-
==============================
8.난 정말이가 우아하게 할 수있는 방법을 모르겠어요. FWIW, 나는 다른 접근을 위해 갈 것이다 : [정보] 당신이있는 거 처리를위한 사용자 정의 모델 클래스를 사용과 그것을위한 XML에서 변환을해야합니다. 당신은 아마이 데이터를 처리하는 더 좋은 방법입니다 찾을거야, 그것은 훨씬 더 간결합니다.
난 정말이가 우아하게 할 수있는 방법을 모르겠어요. FWIW, 나는 다른 접근을 위해 갈 것이다 : [정보] 당신이있는 거 처리를위한 사용자 정의 모델 클래스를 사용과 그것을위한 XML에서 변환을해야합니다. 당신은 아마이 데이터를 처리하는 더 좋은 방법입니다 찾을거야, 그것은 훨씬 더 간결합니다.
그러나 직접 XML을 함께 할 수있는 좋은 방법이있다, 나는 그것을보고 싶어요.
from https://stackoverflow.com/questions/970675/scala-modifying-nested-elements-in-xml by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 어떻게 술어에 의해 두 부분으로 순서를 분할하려면? (0) | 2019.11.15 |
---|---|
[SCALA] 어떻게 아이비 캐시 디렉토리를 구성하는 사용자 별 또는 시스템 전체? (0) | 2019.11.15 |
[SCALA] 스칼라 스트림과 같은 SQL ResultSet의 치료 (0) | 2019.11.14 |
[SCALA] 스칼라에서 예외를 던지는 무슨 일이 "공식적인 규칙"입니다 (0) | 2019.11.14 |
[SCALA] 요소의 고정 된 수의 여러 목록으로 분할 목록 (0) | 2019.11.14 |