다음과 같은 txt 파일에 5000개의 질문이 있습니다.
<quiz>
<que>The question her</que>
<ca>text</ca>
<ia>text</ia>
<ia>text</ia>
<ia>text</ia>
</quiz>
모든 문제를 다음과 같이 변환하기 위해 Ubuntu에서 스크립트를 작성하고 싶습니다.
{
"text":"The question her",
"answer1":"text",
"answer2":"text",
"answer3":"text",
"answer4":"text"
},
답변1
실제로 Python 프로그래밍 없이도 2개의 Unix 유틸리티만 사용하면 이 문제를 해결할 수 있습니다.
따라서 XML이 file.xml
jtm에 있다고 가정하면 이를 다음 json으로 변환합니다.
bash $ jtm file.xml
[
{
"quiz": [
{
"que": "The question her"
},
{
"ca": "text"
},
{
"ia": "text"
},
{
"ia": "text"
},
{
"ia": "text"
}
]
}
]
bash $
그런 다음 일련의 JSON 변환을 적용하면 원하는 결과를 얻을 수 있습니다.
bash $ jtm file.xml | jtc -w'<quiz>l:[1:][-2]' -ei echo { '"answer[-]"': {} }\; -i'<quiz>l:[1:]' | jtc -w'<quiz>l:[-1][:][0]' -w'<quiz>l:[-1][:]' -s | jtc -w'<quiz>l:' -w'<quiz>l:[0]' -s | jtc -w'<quiz>l: <>v' -u'"text"'
[
{
"answer1": "text",
"answer2": "text",
"answer3": "text",
"answer4": "text",
"text": "The question her"
}
]
bash $
그러나 관련된 쉘 스크립트(명령)가 있기 때문에 echo
Python보다 느릴 것입니다. 5000개의 질문에 대해서는 약 1분 안에 실행될 것으로 예상됩니다. (향후 버전에서는 jtc
정적으로 지정된 JSON에서도 보간을 허용할 예정이므로 템플릿 작성에 외부 쉘 스크립트가 필요하지 않고 작업 속도가 매우 빨라질 것입니다)
구문에 대해 궁금한 경우 jtc
여기에서 사용자 가이드를 찾을 수 있습니다.https://github.com/ldn-softdev/jtc/blob/master/User%20Guide.md
답변2
이 xq
도구는 다음에서 제공됩니다.https://kislyuk.github.io/yq/XML을 다음으로 바꾸십시오.
{
"quiz": {
"que": "The question her",
"ca": "text",
"ia": [
"text",
"text",
"text"
]
}
}
ID 필터( xq . file.xml
)를 사용하면 됩니다.
사용하고 싶은 형태에 가까운 형태로 마사지해 드립니다.
xq '.quiz | { text: .que, answers: .ia }' file.xml
어느 출력
{
"text": "The question her",
"answers": [
"text",
"text",
"text"
]
}
answers
열거형 키를 얻기 위해 이 비트를 수정하려면 :
xq '.quiz |
{ text: .que } +
(
[
range(.ia|length) as $i | { key: "answer\($i+1)", value: .ia[$i] }
] | from_entries
)' file.xml
이는 노드를 반복하고 키와 값 세트를 수동으로 생성하여 answer
노드의 열거형 키와 값을 추가합니다. 그런 다음 이를 사용하여 실제 키 값 쌍으로 변환하고 우리가 만든 원본 개체( )에 추가합니다.ia
ia
from_entries
{ text: .que }
산출:
{
"text": "The question her",
"answer1": "text",
"answer2": "text",
"answer3": "text"
}
XML 문서에 quiz
특정 루트 노드 아래에 여러 노드가 포함되어 있는 경우 위의 표현식을 변경하여 .quiz
각 노드를 변환하고 결과 개체를 배열에 넣을 수 있습니다.jq
.[].quiz[]
xq '.[].quiz[] |
[ { text: .que } +
(
[
range(.ia|length) as $i | { key: "answer\($i+1)", value: .ia[$i] }
] | from_entries
) ]' file.xml
답변3
귀하의 우분투에는 이미 Python이 설치되어 있다고 가정합니다.
#!/usr/bin/python3
import io
import json
import xml.etree.ElementTree
d = """<quiz>
<que>The question her</que>
<ca>text</ca>
<ia>text</ia>
<ia>text</ia>
<ia>text</ia>
</quiz>
"""
s = io.StringIO(d)
# root = xml.etree.ElementTree.parse("filename_here").getroot()
root = xml.etree.ElementTree.parse(s).getroot()
out = {}
i = 1
for child in root:
name, value = child.tag, child.text
if name == 'que':
name = 'question'
else:
name = 'answer%s' % i
i += 1
out[name] = value
print(json.dumps(out))
그것을 저장하고 chmod
텍스트 대신 파일을 입력으로 사용하도록 쉽게 수정할 수 있는 실행 파일로 저장합니다.
편집하다 좋습니다. 더 완전한 스크립트는 다음과 같습니다.
#!/usr/bin/python3
import json
import sys
import xml.etree.ElementTree
def read_file(filename):
root = xml.etree.ElementTree.parse(filename).getroot()
return root
# assule we have a list of <quiz>, contained in some other element
def parse_quiz(quiz_element, out):
i = 1
tmp = {}
for child in quiz_element:
name, value = child.tag, child.text
if name == 'que':
name = 'question'
else:
name = 'answer%s' % i
i += 1
tmp[name] = value
out.append(tmp)
def parse_root(root_element, out):
for child in root_element:
if child.tag == 'quiz':
parse_quiz(child, out)
def convert_xml_to_json(filename):
root = read_file(filename)
out = []
parse_root(root, out)
print(json.dumps(out))
if __name__ == '__main__':
if len(sys.argv) > 1:
convert_xml_to_json(sys.argv[1])
else:
print("Usage: script <filename_with_xml>")
다음 내용으로 파일을 만들었습니다 xmltest
. 이름은 다음과 같습니다.
<questions>
<quiz>
<que>The question her</que>
<ca>text</ca>
<ia>text</ia>
<ia>text</ia>
<ia>text</ia>
</quiz>
<quiz>
<que>Question number 1</que>
<ca>blabla</ca>
<ia>stuff</ia>
</quiz>
</questions>
quiz
따라서 다른 컨테이너 안에 목록이 있습니다.
$ chmod u+x scratch.py
이제 다음 과 같이 시작합니다.
scratch.py filenamewithxml
이것은 나에게 대답을 주었다:
$ ./scratch4.py xmltest
[{"answer3": "text", "answer2": "text", "question": "The question her", "answer4": "text", "answer1": "text"}, {"answer2": "stuff", "question": "Question number 1", "answer1": "blabla"}]
답변4
감사합니다 dgan, 하지만 귀하의 코드: 1은 json 파일 대신 화면에 출력을 인쇄하고 인코딩=utf-8을 지원하지 않으므로 변경했습니다.
##!/usr/bin/python3
import json, codecs
import sys
import xml.etree.ElementTree
def read_file(filename):
root = xml.etree.ElementTree.parse(filename).getroot()
return root
# assule we have a list of <quiz>, contained in some other element
def parse_quiz(quiz_element, out):
i = 1
tmp = {}
for child in quiz_element:
name, value = child.tag, child.text
if name == 'que':
name = 'question'
else:
name = 'answer%s' % i
i += 1
tmp[name] = value
out.append(tmp)
def parse_root(root_element, out):
for child in root_element:
if child.tag == 'quiz':
parse_quiz(child, out)
def convert_xml_to_json(filename):
root = read_file(filename)
out = []
parse_root(root, out)
with open('data.json', 'w') as outfile:
json.dump(out, codecs.getwriter('utf-8')(outfile), sort_keys=True, ensure_ascii=False)
if __name__ == '__main__':
if len(sys.argv) > 1:
convert_xml_to_json(sys.argv[1])
else:
print("Usage: script <filename_with_xml>")
`