Skip to content

Commit

Permalink
Refactor XML parsing to handle error cases and improve logging (#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
royshil authored Oct 15, 2024
1 parent 2194f6b commit 4a57daa
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 34 deletions.
8 changes: 8 additions & 0 deletions data/locale/en-US.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
url_file="URL / File"
setup_data_source="Setup Data Source"
setup_outputs_and_templates="Setup Outputs and Templates"
update_timer_ms="Update Timer (ms)"
run_while_not_visible="Run while not visible?"
send_output_to_stream="Send output to current stream as captions"
output_is_image_url="Output is image URL (fetch and show image)"
render_width="Render Width (px)"
56 changes: 31 additions & 25 deletions src/parsers/xml.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#include "request-data.h"
#include "plugin-support.h"
#include "errors.h"

#include <pugixml.hpp>
#include <obs-module.h>
Expand All @@ -10,34 +11,39 @@ struct request_data_handler_response parse_xml(struct request_data_handler_respo
{
// Parse the response as XML using pugixml
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_string(response.body.c_str());
if (!result) {
obs_log(LOG_INFO, "Failed to parse XML response: %s", result.description());
// Return an error response
struct request_data_handler_response responseFail;
responseFail.error_message = result.description();
responseFail.status_code = URL_SOURCE_REQUEST_PARSING_ERROR_CODE;
return responseFail;
}
std::string parsed_output = "";
// Get the output value
if (request_data->output_xpath != "") {
pugi::xpath_node_set nodes = doc.select_nodes(request_data->output_xpath.c_str());
if (nodes.size() > 0) {
parsed_output = nodes[0].node().text().get();
try {
pugi::xml_parse_result result = doc.load_string(response.body.c_str());
if (!result) {

obs_log(LOG_INFO, "Failed to parse XML response: %s", result.description());
return make_fail_parse_response(result.description());
}
if (doc.empty()) {
obs_log(LOG_INFO, "Failed to parse XML response: Empty XML");
return make_fail_parse_response("Empty XML");
}
std::string parsed_output = "";
// Get the output value
if (request_data->output_xpath != "") {
obs_log(LOG_INFO, "Parsing XML with XPath: %s",
request_data->output_xpath.c_str());
pugi::xpath_node_set nodes =
doc.select_nodes(request_data->output_xpath.c_str());
if (nodes.size() > 0) {
parsed_output = nodes[0].node().text().get();
} else {
obs_log(LOG_INFO, "Failed to get XML value");
return make_fail_parse_response("Failed to get XML value");
}
} else {
obs_log(LOG_INFO, "Failed to get XML value");
// Return an error response
struct request_data_handler_response responseFail;
responseFail.error_message = "Failed to get XML value";
responseFail.status_code = URL_SOURCE_REQUEST_PARSING_ERROR_CODE;
return responseFail;
// Return the whole XML object
parsed_output = response.body;
}
} else {
// Return the whole XML object
parsed_output = response.body;
response.body_parts_parsed.push_back(parsed_output);
} catch (const std::exception &e) {
obs_log(LOG_INFO, "Failed to parse XML response: %s", e.what());
return make_fail_parse_response(e.what());
}
response.body_parts_parsed.push_back(parsed_output);
return response;
}

Expand Down
2 changes: 2 additions & 0 deletions src/plugin-support.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ extern const char *PLUGIN_VERSION;

void obs_log(int log_level, const char *format, ...);

#define MT_ obs_module_text

#ifdef __cplusplus
}
#endif
17 changes: 8 additions & 9 deletions src/url-source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,31 +247,30 @@ obs_properties_t *url_source_properties(void *data)
obs_properties_t *ppts = obs_properties_create();
// URL input string
obs_property_t *urlprop =
obs_properties_add_text(ppts, "url", "URL / File", OBS_TEXT_DEFAULT);
obs_properties_add_text(ppts, "url", MT_("url_file"), OBS_TEXT_DEFAULT);
// Disable the URL input since it's setup via the Request Builder dialog
obs_property_set_enabled(urlprop, false);

// Add button to open the Request Builder dialog
obs_properties_add_button2(ppts, "setup_request_button", "Setup Data Source",
obs_properties_add_button2(ppts, "setup_request_button", MT_("setup_data_source"),
setup_request_button_click, usd);

obs_properties_add_button2(ppts, "output_mapping_and_template",
"Setup Outputs and Templates",
MT_("setup_outputs_and_templates"),
output_mapping_and_template_button_click, usd);

// Update timer setting in milliseconds
obs_properties_add_int(ppts, "update_timer", "Update Timer (ms)", 100, 1000000, 100);
obs_properties_add_int(ppts, "update_timer", MT_("update_timer_ms"), 100, 1000000, 100);

// Run timer while not visible
obs_properties_add_bool(ppts, "run_while_not_visible", "Run while not visible?");
obs_properties_add_bool(ppts, "run_while_not_visible", MT_("run_while_not_visible"));

obs_properties_add_bool(ppts, "send_to_stream",
"Send output to current stream as captions");
obs_properties_add_bool(ppts, "send_to_stream", MT_("send_output_to_stream"));

// Is Image URL boolean checkbox
obs_properties_add_bool(ppts, "is_image_url", "Output is image URL (fetch and show image)");
obs_properties_add_bool(ppts, "is_image_url", MT_("output_is_image_url"));

obs_properties_add_int(ppts, "render_width", "Render Width (px)", 100, 10000, 1);
obs_properties_add_int(ppts, "render_width", MT_("render_width"), 100, 10000, 1);

// Add a informative text about the plugin
obs_properties_add_text(
Expand Down

0 comments on commit 4a57daa

Please sign in to comment.