Mercurial > hg > orthanc
comparison Core/DicomParsing/DicomWebJsonVisitor.cpp @ 3221:4be505c2ac56
Separation of ideographic and phonetic characters in DICOMweb JSON and XML
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 14 Feb 2019 14:04:04 +0100 |
parents | 810772486249 |
children | b88937ef597b |
comparison
equal
deleted
inserted
replaced
3220:1a0b4db799e8 | 3221:4be505c2ac56 |
---|---|
41 #include <boost/math/special_functions/round.hpp> | 41 #include <boost/math/special_functions/round.hpp> |
42 #include <boost/lexical_cast.hpp> | 42 #include <boost/lexical_cast.hpp> |
43 | 43 |
44 | 44 |
45 static const char* const KEY_ALPHABETIC = "Alphabetic"; | 45 static const char* const KEY_ALPHABETIC = "Alphabetic"; |
46 static const char* const KEY_IDEOGRAPHIC = "Ideographic"; | |
47 static const char* const KEY_PHONETIC = "Phonetic"; | |
46 static const char* const KEY_BULK_DATA_URI = "BulkDataURI"; | 48 static const char* const KEY_BULK_DATA_URI = "BulkDataURI"; |
47 static const char* const KEY_INLINE_BINARY = "InlineBinary"; | 49 static const char* const KEY_INLINE_BINARY = "InlineBinary"; |
48 static const char* const KEY_SQ = "SQ"; | 50 static const char* const KEY_SQ = "SQ"; |
51 static const char* const KEY_TAG = "tag"; | |
49 static const char* const KEY_VALUE = "Value"; | 52 static const char* const KEY_VALUE = "Value"; |
50 static const char* const KEY_VR = "vr"; | 53 static const char* const KEY_VR = "vr"; |
51 | 54 |
52 | 55 |
53 namespace Orthanc | 56 namespace Orthanc |
54 { | 57 { |
55 #if ORTHANC_ENABLE_PUGIXML == 1 | 58 #if ORTHANC_ENABLE_PUGIXML == 1 |
59 static void DecomposeXmlPersonName(pugi::xml_node& target, | |
60 const std::string& source) | |
61 { | |
62 std::vector<std::string> tokens; | |
63 Toolbox::TokenizeString(tokens, source, '^'); | |
64 | |
65 if (tokens.size() >= 1) | |
66 { | |
67 target.append_child("FamilyName").text() = tokens[0].c_str(); | |
68 } | |
69 | |
70 if (tokens.size() >= 2) | |
71 { | |
72 target.append_child("GivenName").text() = tokens[1].c_str(); | |
73 } | |
74 | |
75 if (tokens.size() >= 3) | |
76 { | |
77 target.append_child("MiddleName").text() = tokens[2].c_str(); | |
78 } | |
79 | |
80 if (tokens.size() >= 4) | |
81 { | |
82 target.append_child("NamePrefix").text() = tokens[3].c_str(); | |
83 } | |
84 | |
85 if (tokens.size() >= 5) | |
86 { | |
87 target.append_child("NameSuffix").text() = tokens[4].c_str(); | |
88 } | |
89 } | |
90 | |
56 static void ExploreXmlDataset(pugi::xml_node& target, | 91 static void ExploreXmlDataset(pugi::xml_node& target, |
57 const Json::Value& source) | 92 const Json::Value& source) |
58 { | 93 { |
94 // http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_F.3.html#table_F.3.1-1 | |
59 assert(source.type() == Json::objectValue); | 95 assert(source.type() == Json::objectValue); |
60 | 96 |
61 Json::Value::Members members = source.getMemberNames(); | 97 Json::Value::Members members = source.getMemberNames(); |
62 for (size_t i = 0; i < members.size(); i++) | 98 for (size_t i = 0; i < members.size(); i++) |
63 { | 99 { |
64 const DicomTag tag = FromDcmtkBridge::ParseTag(members[i]); | 100 const DicomTag tag = FromDcmtkBridge::ParseTag(members[i]); |
65 const Json::Value& content = source[members[i]]; | 101 const Json::Value& content = source[members[i]]; |
66 | 102 |
67 assert(content.type() == Json::objectValue && | 103 assert(content.type() == Json::objectValue && |
68 content.isMember("vr") && | 104 content.isMember(KEY_VR) && |
69 content["vr"].type() == Json::stringValue); | 105 content[KEY_VR].type() == Json::stringValue); |
70 const std::string vr = content["vr"].asString(); | 106 const std::string vr = content[KEY_VR].asString(); |
71 | 107 |
72 const std::string keyword = FromDcmtkBridge::GetTagName(tag, ""); | 108 const std::string keyword = FromDcmtkBridge::GetTagName(tag, ""); |
73 | 109 |
74 pugi::xml_node node = target.append_child("DicomAttribute"); | 110 pugi::xml_node node = target.append_child("DicomAttribute"); |
75 node.append_attribute("tag").set_value(members[i].c_str()); | 111 node.append_attribute(KEY_TAG).set_value(members[i].c_str()); |
76 node.append_attribute("vr").set_value(vr.c_str()); | 112 node.append_attribute(KEY_VR).set_value(vr.c_str()); |
77 | 113 |
78 if (keyword != std::string(DcmTag_ERROR_TagName)) | 114 if (keyword != std::string(DcmTag_ERROR_TagName)) |
79 { | 115 { |
80 node.append_attribute("keyword").set_value(keyword.c_str()); | 116 node.append_attribute("keyword").set_value(keyword.c_str()); |
81 } | 117 } |
97 ExploreXmlDataset(child, content[KEY_VALUE][j]); | 133 ExploreXmlDataset(child, content[KEY_VALUE][j]); |
98 } | 134 } |
99 } | 135 } |
100 if (vr == "PN") | 136 if (vr == "PN") |
101 { | 137 { |
102 if (content[KEY_VALUE][j].isMember(KEY_ALPHABETIC) && | 138 bool hasAlphabetic = (content[KEY_VALUE][j].isMember(KEY_ALPHABETIC) && |
103 content[KEY_VALUE][j][KEY_ALPHABETIC].type() == Json::stringValue) | 139 content[KEY_VALUE][j][KEY_ALPHABETIC].type() == Json::stringValue); |
140 | |
141 bool hasIdeographic = (content[KEY_VALUE][j].isMember(KEY_IDEOGRAPHIC) && | |
142 content[KEY_VALUE][j][KEY_IDEOGRAPHIC].type() == Json::stringValue); | |
143 | |
144 bool hasPhonetic = (content[KEY_VALUE][j].isMember(KEY_PHONETIC) && | |
145 content[KEY_VALUE][j][KEY_PHONETIC].type() == Json::stringValue); | |
146 | |
147 if (hasAlphabetic || | |
148 hasIdeographic || | |
149 hasPhonetic) | |
104 { | 150 { |
105 std::vector<std::string> tokens; | |
106 Toolbox::TokenizeString(tokens, content[KEY_VALUE][j][KEY_ALPHABETIC].asString(), '^'); | |
107 | |
108 pugi::xml_node child = node.append_child("PersonName"); | 151 pugi::xml_node child = node.append_child("PersonName"); |
109 child.append_attribute("number").set_value(number.c_str()); | 152 child.append_attribute("number").set_value(number.c_str()); |
110 | 153 |
111 pugi::xml_node name = child.append_child(KEY_ALPHABETIC); | 154 if (hasAlphabetic) |
112 | |
113 if (tokens.size() >= 1) | |
114 { | 155 { |
115 name.append_child("FamilyName").text() = tokens[0].c_str(); | 156 pugi::xml_node name = child.append_child(KEY_ALPHABETIC); |
157 DecomposeXmlPersonName(name, content[KEY_VALUE][j][KEY_ALPHABETIC].asString()); | |
116 } | 158 } |
117 | 159 |
118 if (tokens.size() >= 2) | 160 if (hasIdeographic) |
119 { | 161 { |
120 name.append_child("GivenName").text() = tokens[1].c_str(); | 162 pugi::xml_node name = child.append_child(KEY_IDEOGRAPHIC); |
163 DecomposeXmlPersonName(name, content[KEY_VALUE][j][KEY_IDEOGRAPHIC].asString()); | |
121 } | 164 } |
122 | 165 |
123 if (tokens.size() >= 3) | 166 if (hasPhonetic) |
124 { | 167 { |
125 name.append_child("MiddleName").text() = tokens[2].c_str(); | 168 pugi::xml_node name = child.append_child(KEY_PHONETIC); |
126 } | 169 DecomposeXmlPersonName(name, content[KEY_VALUE][j][KEY_PHONETIC].asString()); |
127 | |
128 if (tokens.size() >= 4) | |
129 { | |
130 name.append_child("NamePrefix").text() = tokens[3].c_str(); | |
131 } | |
132 | |
133 if (tokens.size() >= 5) | |
134 { | |
135 name.append_child("NameSuffix").text() = tokens[4].c_str(); | |
136 } | 170 } |
137 } | 171 } |
138 } | 172 } |
139 else | 173 else |
140 { | 174 { |
515 case ValueRepresentation_PersonName: | 549 case ValueRepresentation_PersonName: |
516 { | 550 { |
517 Json::Value value = Json::objectValue; | 551 Json::Value value = Json::objectValue; |
518 if (!tokens[i].empty()) | 552 if (!tokens[i].empty()) |
519 { | 553 { |
520 value[KEY_ALPHABETIC] = tokens[i]; | 554 std::vector<std::string> components; |
555 Toolbox::TokenizeString(components, tokens[i], '='); | |
556 | |
557 if (components.size() >= 1) | |
558 { | |
559 value[KEY_ALPHABETIC] = components[0]; | |
560 } | |
561 | |
562 if (components.size() >= 2) | |
563 { | |
564 value[KEY_IDEOGRAPHIC] = components[1]; | |
565 } | |
566 | |
567 if (components.size() >= 3) | |
568 { | |
569 value[KEY_PHONETIC] = components[2]; | |
570 } | |
521 } | 571 } |
572 | |
522 node[KEY_VALUE].append(value); | 573 node[KEY_VALUE].append(value); |
523 break; | 574 break; |
524 } | 575 } |
525 | 576 |
526 case ValueRepresentation_IntegerString: | 577 case ValueRepresentation_IntegerString: |