일부 지정된 태그의 특정 문자열을 XML 파일의 태그에 포함된 다른 문자열로 바꿔야 합니다.
가 나타나는 모든 항목을 검색하고, 태그 내에(다른 태그 내에) 있는 경우에만 다음 an example
으로 바꿔야 합니다.<b>a test</b>
<a> ... </a>
- 입력 예:
<c>This is an example. <a>This is an example;</a></c>
- 원하는 출력:
<c>This is an example. <a>This is <b>a test;</b></a></c>
답변1
당신이 원하는 것 같습니다
- XML 문서의 노드 값
an example;
에서 텍스트를 제거하고 ,/c/a
/c/a
이름이 지정된 노드에b
값이 있는 하위 노드를 추가합니다a test;
.
xmlstarlet
셸에서 이 작업을 쉽게 수행할 수 있습니다.
xmlstarlet ed -u '/c/a' -x 'substring-before(text(), "an example;")' file.xml |
xmlstarlet ed -s '/c/a' -t elem -n 'b' -v 'a test;'
xmlstarlet
질문의 예제 문서에 대한 첫 번째 호출은 /c/a
노드 값에서 일부 텍스트가 제거된 다음 출력을 생성합니다.
<?xml version="1.0"?>
<c>This is an example. <a>This is </a></c>
두 번째 호출은 이 수정된 문서를 가져와 노드를 도입하여 다음을 생성합니다 /c/a/b
.
<?xml version="1.0"?>
<c>This is an example. <a>This is <b>a test;</b></a></c>
이러한 xmlstarlet
호출은 단일 명령으로 결합될 수 있습니다. 아래에서는 --inplace
원본 문서의 내부 편집 에도 긴 옵션을 사용했습니다 (이는 설명을 위한 것일 뿐이므로 --inplace
변환이 작동하는지 확인하려면 먼저 실행하지 않고 실행해야 합니다).
xmlstarlet ed --inplace \
--update '/c/a' -x 'substring-before(text(), "an example;")' \
--subnode '/c/a' -t elem -n 'b' -v 'a test;' file.xml
위의 내용을 일반화하여 a
텍스트가 포함된 노드에서 두 가지 편집을 수행합니다 an example;
(질문에서 실제로 요구되는 내용입니다).
xmlstarlet ed \
--var paths '//a[contains(text(), "an example;")]' \
--update '$paths' -x 'substring-before(text(), "an example;")' \
--subnode '$paths' -t elem -n 'b' -v 'a test;' file.xml
여기서 유일하게 새로운 점은 편집하려는 모든 노드의 경로를 먼저 내부 변수에 저장한다는 것입니다 $paths
. 그런 다음 --update
에서 이러한 경로를 참조하고 수정합니다 --subnode
.