diff --git a/Source/Checker/Checker.cpp b/Source/Checker/Checker.cpp index fcc2a34e..1d292692 100644 --- a/Source/Checker/Checker.cpp +++ b/Source/Checker/Checker.cpp @@ -83,6 +83,40 @@ int tfsxml_next_named(tfsxml_string* tfsxml_priv, tfsxml_string* result, const c return -1; } +//--------------------------------------------------------------------------- +int tfsxml_hasvalue(tfsxml_string* priv) +{ + const char* buf = priv->buf; + unsigned len = priv->len; + while (len) + { + len--; + switch (*buf) + { + case '\n': + case '\t': + case '\r': + case ' ': + break; + case '<': + if (!len) + return 1; + buf++; + switch (*buf) + { + case '!': + case '/': + return 0; + default: + return -1; + } + default: + return 0; + } + } + return 1; +} + //--------------------------------------------------------------------------- std::string tokenize(const std::string& scope, const std::string& list, const std::string& delimiter) { @@ -246,13 +280,15 @@ std::string PolicyChecker::PolicyElement::to_string(size_t level, bool verbose) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -PolicyChecker::RuleElement::RuleElement() : resolved(false), pass(false), tracks(0) +PolicyChecker::RuleElement::RuleElement() : resolved(false), pass(false), tracks(0), source(NULL) { } //--------------------------------------------------------------------------- PolicyChecker::RuleElement::~RuleElement() { + if (source) + delete source; } //--------------------------------------------------------------------------- @@ -262,71 +298,73 @@ void PolicyChecker::RuleElement::reset() pass=false; tracks=0; values.clear(); + if (source) + source->values.clear(); } //--------------------------------------------------------------------------- -bool PolicyChecker::RuleElement::compare(const std::string& value) +bool PolicyChecker::RuleElement::compare(const std::string& v1, const std::string& v2) { bool to_return = false; char* val_end=NULL; - double val = strtod(value.c_str(), &val_end); + double val = strtod(v2.c_str(), &val_end); char* ref_end=NULL; - double ref = strtod(requested.c_str(), &ref_end); + double ref = strtod(v1.c_str(), &ref_end); if (operand=="starts with") { - to_return = value.rfind(requested, 0) == 0; + to_return = v2.rfind(v1, 0) == 0; } else if (operand=="must not start with") { - to_return = value.rfind(requested, 0) != 0; + to_return = v2.rfind(v1, 0) != 0; } else if (operand == "<") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val < ref; else - to_return = strcmp(value.c_str(), requested.c_str()) < 0; + to_return = strcmp(v2.c_str(), v1.c_str()) < 0; } else if (operand == "<=") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val <= ref; else - to_return = strcmp(value.c_str(), requested.c_str()) <= 0; + to_return = strcmp(v2.c_str(), v1.c_str()) <= 0; } else if (operand == "=") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val == ref; else - to_return = strcmp(value.c_str(), requested.c_str()) == 0; + to_return = strcmp(v2.c_str(), v1.c_str()) == 0; } else if (operand == "!=") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val != ref; else - to_return = strcmp(value.c_str(), requested.c_str()) != 0; + to_return = strcmp(v2.c_str(), v1.c_str()) != 0; } else if (operand == ">=") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val >= ref; else - to_return = strcmp(value.c_str(), requested.c_str()) >= 0; + to_return = strcmp(v2.c_str(), v1.c_str()) >= 0; } else if (operand == ">") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val > ref; else - to_return = strcmp(value.c_str(), requested.c_str()) > 0; + to_return = strcmp(v2.c_str(), v1.c_str()) > 0; } if (!to_return) - failing_values.push_back(value); + failing_values.push_back(v2); return to_return; } @@ -363,12 +401,37 @@ void PolicyChecker::RuleElement::resolve() } else if (operand=="starts with" || operand=="must not start with" || operand=="<" || operand=="<=" || operand=="=" || operand=="!=" || operand==">=" || operand==">") { - if (values.empty()) - pass = operand=="must not start with" ? true : false; - else if (occurrence=="all") - pass = std::all_of(values.begin(), values.end(), std::bind(&PolicyChecker::RuleElement::compare, this, std::placeholders::_1)); - else - pass = std::any_of(values.begin(), values.end(), std::bind(&PolicyChecker::RuleElement::compare, this, std::placeholders::_1)); + if (values.empty()) + pass = operand=="must not start with" ? true : false; + else if (occurrence=="all") //std::bind(&PolicyChecker::RuleElement::compare, this, requested, std::placeholders::_1) + { + pass = std::all_of(values.begin(), values.end(), [this](const std::string& value) { + if (source) + { + if (source->occurrence=="all") + return std::all_of(source->values.begin(), source->values.end(), std::bind(&PolicyChecker::RuleElement::compare, this, std::placeholders::_1, value)); + else + return std::any_of(source->values.begin(), source->values.end(), std::bind(&PolicyChecker::RuleElement::compare, this, std::placeholders::_1, value)); + } + else + return compare(requested, value); + }); + } + else + { + pass = std::any_of(values.begin(), values.end(), [this](const std::string& value) { + if (source) + { + if (source->occurrence=="all") + return std::all_of(source->values.begin(), source->values.end(), std::bind(&PolicyChecker::RuleElement::compare, this, std::placeholders::_1, value)); + else + return std::any_of(source->values.begin(), source->values.end(), std::bind(&PolicyChecker::RuleElement::compare, this, std::placeholders::_1, value)); + } + else + return compare(requested, value); + }); + } + } resolved=true; @@ -419,13 +482,35 @@ std::string PolicyChecker::RuleElement::to_string(size_t level, bool verbose) ss << indent(level) << "level.empty()) ss << " level=\"" << xml_encode(this->level) << "\""; if (result()>RESULT_PASS || verbose) - ss << " requested=\"" << xml_encode(requested) << "\" actual=\"" << xml_encode(value_str) << "\""; - ss << " outcome=\"" << outcome_str << "\"/>" << std::endl; + ss << " requested=\"" + << (source && source->values.size() ? xml_encode(source->values.front()) : xml_encode(requested)) + << "\" actual=\"" << xml_encode(value_str) << "\""; + ss << " outcome=\"" << outcome_str << "\""; + + if (source) + { + ss << ">" << std::endl; + + ss << indent(level +1) << "scope.empty()) + ss << " scope=\"" << xml_encode(source->scope) << "\""; + ss << " value=\"" << xml_encode(source->field) + << "\" tracktype=\"" << xml_encode(source->tracktype) + << "\" occurrence=\"" << (source->occurrence.size() ? xml_encode(source->occurrence) : "*") + << "\"/>" << std::endl; + + ss << indent(level) << "" << std::endl; + } + else + ss << "/>" << std::endl; return ss.str(); } @@ -487,27 +572,75 @@ PolicyChecker::RuleElement* PolicyChecker::parse_rule(tfsxml_string& tfsxml_priv rule->operand=tfsxml_decode(attribute_value); } - std::string occurrence=rule->occurrence; - if (occurrence.empty() || occurrence=="all" || occurrence=="any") - occurrence="*"; + if (!tfsxml_hasvalue(&tfsxml_priv)) + { + tfsxml_string value; + if (!tfsxml_value(&tfsxml_priv, &value)) + rule->requested = std::string(value.buf, value.len); + } + else + { + if (!tfsxml_enter(&tfsxml_priv)) + { + tfsxml_string value; + while (!tfsxml_next(&tfsxml_priv, &value)) + { + if (!tfsxml_strcmp_charp(value, "source")) + { + if (rule->source) + delete rule->source; + rule->source = new RuleElement::Source(); + + while (!tfsxml_attr(&tfsxml_priv, &attribute_name, &attribute_value)) + { + if (!tfsxml_strcmp_charp(attribute_name, "scope")) + rule->source->scope=tfsxml_decode(attribute_value); + else if (!tfsxml_strcmp_charp(attribute_name, "value")) + rule->source->field=tfsxml_decode(attribute_value); + else if (!tfsxml_strcmp_charp(attribute_name, "tracktype")) + rule->source->tracktype=tfsxml_decode(attribute_value); + else if (!tfsxml_strcmp_charp(attribute_name, "occurrence")) + rule->source->occurrence=tfsxml_decode(attribute_value); + } + + // Check for currently unsupported features + if (rule->scope=="mmt") + supported=false; - tfsxml_string value; - if (!tfsxml_value(&tfsxml_priv, &value)) - rule->requested=std::string(value.buf, value.len); + if (rule->scope.empty() || rule->scope=="mi") + { + std::stringstream ss; + ss << "mi:MediaInfo/mi:track[@type='" + << rule->source->tracktype << "'][" + << ((rule->source->occurrence.empty() || rule->source->occurrence=="all" || rule->source->occurrence=="any") ? "*" : rule->source->occurrence) + << "]" + << tokenize(rule->source->scope, rule->source->field, "/"); + rule->source->path=parse_path(ss.str()); + } + break; + } + } + tfsxml_leave(&tfsxml_priv); + } + } // Check for presence of _StringX or TimeCode* element in policy size_t index=rule->field.find_last_not_of("0123456789"); if ((index!=std::string::npos && index>=6 && rule->field.substr(index-6, 7)=="_String") || rule->field.find("TimeCode")==0 || rule->field.rfind("_Total")==rule->field.size()-6) full=true; -// Check for currently unsupported features - if (rule->scope=="mmt" || rule->requested=="compare") + // Check for currently unsupported features + if (rule->scope=="mmt" || rule->requested =="compare") supported=false; if (rule->scope.empty() || rule->scope=="mi") { std::stringstream ss; - ss << "mi:MediaInfo/mi:track[@type='" << rule->tracktype << "'][" << occurrence << "]" << tokenize(rule->scope, rule->field, "/"); + ss << "mi:MediaInfo/mi:track[@type='" + << rule->tracktype + << "'][" + << ((rule->occurrence.empty() || rule->occurrence=="all" || rule->occurrence=="any") ? "*" : rule->occurrence) + << "]" << tokenize(rule->scope, rule->field, "/"); rule->xpath=ss.str(); rule->path=parse_path(rule->xpath); } @@ -569,7 +702,7 @@ void PolicyChecker::add_policy(const std::string& policy) tfsxml_string tfsxml_priv; tfsxml_string result; - tfsxml_init(&tfsxml_priv, (const void*)policy.c_str(), policy.size()); + tfsxml_init(&tfsxml_priv, (const void*)policy.c_str(), policy.size(), 0); while (!tfsxml_next(&tfsxml_priv, &result)) { if (!tfsxml_strcmp_charp(result, "policy")) @@ -583,12 +716,11 @@ void PolicyChecker::add_policy(const std::string& policy) } //--------------------------------------------------------------------------- -void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vector rules, size_t level) +void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vector rules, std::vector sources, size_t level) { - if (rules.empty()) + if (rules.empty() && sources.empty()) return; - tfsxml_string tfsxml_priv_save = tfsxml_priv; if (!tfsxml_enter(&tfsxml_priv)) { std::map occurrences; @@ -597,8 +729,7 @@ void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vector matching_rules; - - std::string field = std::string(result.buf, result.len); + std::vector matching_sources; for (size_t pos = 0; pos < rules.size(); pos++) { if (level < rules[pos]->path.size() && path_is_matching(tfsxml_priv, result, rules[pos]->path[level], occurrences[&rules[pos]->path[level]])) @@ -606,9 +737,9 @@ void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vectorscope.empty() || rules[pos]->scope == "mi")) // at track level rules[pos]->tracks++; - tfsxml_string tfsxml_priv_copy = tfsxml_priv; if (level == rules[pos]->path.size() - 1) { + tfsxml_string tfsxml_priv_copy = tfsxml_priv; tfsxml_string value; if (!tfsxml_value(&tfsxml_priv_copy, &value)) rules[pos]->values.push_back(std::string(value.buf, value.len)); @@ -618,11 +749,26 @@ void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vectorsource && level < sources[pos]->source->path.size() && path_is_matching(tfsxml_priv, result, sources[pos]->source->path[level], occurrences[&sources[pos]->source->path[level]])) + { + if (level == sources[pos]->source->path.size() - 1) + { + tfsxml_string tfsxml_priv_copy = tfsxml_priv; + tfsxml_string value; + if (!tfsxml_value(&tfsxml_priv_copy, &value)) + sources[pos]->source->values.push_back(std::string(value.buf, value.len)); + } + else + matching_sources.push_back(sources[pos]); + } + } + + if (!matching_rules.empty() || !matching_sources.empty()) + parse_node(tfsxml_priv, matching_rules, matching_sources, level + 1); } } - tfsxml_priv=tfsxml_priv_save; } //--------------------------------------------------------------------------- @@ -636,7 +782,7 @@ int PolicyChecker::analyze(const std::string& report, bool verbose, std::string& ss << indent(level ) << "MediaConch" << std::endl; tfsxml_string tfsxml_priv; tfsxml_string result; - tfsxml_init(&tfsxml_priv, (const void*)report.c_str(), report.size()); + tfsxml_init(&tfsxml_priv, (const void*)report.c_str(), report.size(), 0); while (!tfsxml_next_named(&tfsxml_priv, &result, "MediaArea")) { if (!tfsxml_enter(&tfsxml_priv)) @@ -655,7 +801,7 @@ int PolicyChecker::analyze(const std::string& report, bool verbose, std::string& } ss << indent(level++) << "" << std::endl; - parse_node(tfsxml_priv, rules, 0); + parse_node(tfsxml_priv, rules, rules, 0); for (size_t pos=0; posto_string(level, verbose); ss << indent(--level) << "" << std::endl; diff --git a/Source/Checker/Checker.h b/Source/Checker/Checker.h index 9fb3289b..f76e65b8 100644 --- a/Source/Checker/Checker.h +++ b/Source/Checker/Checker.h @@ -18,7 +18,7 @@ //--------------------------------------------------------------------------- #ifndef TFSXML_NAMESPACE #define TFSXML_NAMESPACE 1 -#endif // TFSXML_NAMESPACEs +#endif // TFSXML_NAMESPACE #include "ThirdParty/tfsxml/tfsxml.h" #include "Path.h" @@ -73,11 +73,21 @@ class PolicyChecker class RuleElement : public Element { public: + struct Source + { + std::vector path; + std::vector values; + std::string scope; + std::string field; + std::string tracktype; + std::string occurrence; + }; + RuleElement(); ~RuleElement(); void reset(); - bool compare(const std::string& value); + bool compare(const std::string& v1, const std::string& v2); virtual void resolve(); virtual Result result(); @@ -95,6 +105,7 @@ class PolicyChecker std::string requested; std::vector values; std::vector failing_values; + Source* source; size_t tracks; private: @@ -129,7 +140,7 @@ class PolicyChecker RuleElement* parse_rule(tfsxml::tfsxml_string& tfsxml_priv); PolicyElement* parse_policy(tfsxml::tfsxml_string& tfsxml_priv); - void parse_node(tfsxml::tfsxml_string& tfsxml_priv, std::vector rules, size_t level); + void parse_node(tfsxml::tfsxml_string& tfsxml_priv, std::vector rules, std::vector sources, size_t level); std::vector policies; std::vector rules; diff --git a/Source/Checker/Path.cpp b/Source/Checker/Path.cpp index c527c586..aeec50e4 100644 --- a/Source/Checker/Path.cpp +++ b/Source/Checker/Path.cpp @@ -112,6 +112,7 @@ std::vector parse_path(const std::string& xpath) //--------------------------------------------------------------------------- bool path_is_matching(tfsxml_string& tfsxml_priv, tfsxml_string& node, PathElement path, size_t& occurrence) { + tfsxml_string tfsxml_priv_local = tfsxml_priv; tfsxml_string value; // compare names @@ -125,10 +126,8 @@ bool path_is_matching(tfsxml_string& tfsxml_priv, tfsxml_string& node, PathEleme tfsxml_string attribute_name; tfsxml_string attribute_value; - tfsxml_string tfsxml_priv_save=tfsxml_priv; - while (!tfsxml_attr(&tfsxml_priv, &attribute_name, &attribute_value)) + while (!tfsxml_attr(&tfsxml_priv_local, &attribute_name, &attribute_value)) attributes[std::string(attribute_name.buf, attribute_name.len)]=std::string(attribute_value.buf, attribute_value.len); - tfsxml_priv=tfsxml_priv_save; std::map::iterator it=path.attributes.begin(); while (it!=path.attributes.end()) diff --git a/Source/Common/JS_Tree.cpp b/Source/Common/JS_Tree.cpp index eb567426..0dec66ed 100644 --- a/Source/Common/JS_Tree.cpp +++ b/Source/Common/JS_Tree.cpp @@ -700,8 +700,18 @@ int JsTree::rule_to_js_tree(MediaConchLib::XSLT_Policy_Rule* rule, std::string& ss << "\",\"level\":\"" << unified_json_value(rule->level); ss << "\",\"occurrence\":\"" << unified_json_value(rule->occurrence); ss << "\",\"ope\":\"" << unified_json_value(rule->ope); - ss << "\",\"value\":\"" << unified_json_value(rule->value); - ss <<"\"}}"; + if (rule->source) + { + ss << "\",\"source\":{"; + ss << "\"tracktype\":\"" << unified_json_value(rule->source->tracktype); + ss << "\",\"field\":\"" << unified_json_value(rule->source->field); + ss << "\",\"scope\":\"" << unified_json_value(rule->source->scope); + ss << "\",\"occurrence\":\"" << unified_json_value(rule->source->occurrence); + ss <<"\"}"; + } + else + ss << "\",\"value\":\"" << unified_json_value(rule->value) << "\""; + ss <<"}}"; json = ss.str(); return 0; diff --git a/Source/Common/MediaConchLib.cpp b/Source/Common/MediaConchLib.cpp index 1e8f1118..0a88082d 100644 --- a/Source/Common/MediaConchLib.cpp +++ b/Source/Common/MediaConchLib.cpp @@ -690,7 +690,20 @@ std::string MediaConchLib::XSLT_Policy_Rule::to_str() const out << ",occurrence:\"" << occurrence << "\""; if (ope.size()) out << ",\"ope\":\"" << ope << "\""; - if (value.size()) + if (source) + { + out << ",source:{"; + if (source->tracktype.size()) + out << ",\"tracktype\":\"" << source->tracktype << "\""; + if (source->field.size()) + out << ",\"field\":\"" << source->field << "\""; + if (source->scope.size()) + out << ",\"scope\":\"" << source->scope << "\""; + if (source->occurrence.size()) + out << ",occurrence:\"" << source->occurrence << "\""; + out << "}"; + } + else if (value.size()) out << ",\"value\":\"" << value << "\""; out << "}"; return out.str(); diff --git a/Source/Common/MediaConchLib.h b/Source/Common/MediaConchLib.h index 8e92faa7..3356b4bc 100644 --- a/Source/Common/MediaConchLib.h +++ b/Source/Common/MediaConchLib.h @@ -175,7 +175,18 @@ class MediaConchLib struct XSLT_Policy_Rule { - XSLT_Policy_Rule() : id(-1) {} + XSLT_Policy_Rule() : id(-1), source(NULL) {} + ~XSLT_Policy_Rule() { + if (source) + delete source; + } + + struct Source { + std::string tracktype; + std::string field; + std::string scope; + std::string occurrence; + }; int id; std::string name; @@ -186,6 +197,7 @@ class MediaConchLib std::string occurrence; std::string ope; std::string value; + Source* source; std::string to_str() const; }; diff --git a/Source/Common/XsltPolicy.cpp b/Source/Common/XsltPolicy.cpp index f40536e5..1b6a55fe 100644 --- a/Source/Common/XsltPolicy.cpp +++ b/Source/Common/XsltPolicy.cpp @@ -68,11 +68,15 @@ size_t XsltPolicyRule::rule_id = 0; XsltPolicyRule::XsltPolicyRule() : XsltPolicyNode() { kind = XSLT_POLICY_RULE; + source = NULL; + } //--------------------------------------------------------------------------- XsltPolicyRule::~XsltPolicyRule() { + if (source) + delete source; } //--------------------------------------------------------------------------- @@ -89,6 +93,17 @@ XsltPolicyRule::XsltPolicyRule(const XsltPolicyRule* r) : XsltPolicyNode(r) this->level = r->level; this->occurrence = r->occurrence; this->value = r->value; + if (r->source) + { + if (this->source) + delete this->source; + + this->source = new Source; + this->source->track_type = r->source->track_type; + this->source->field = r->source->field; + this->source->scope = r->source->scope; + this->source->occurrence = r->source->occurrence; + } } //--------------------------------------------------------------------------- @@ -105,6 +120,17 @@ XsltPolicyRule::XsltPolicyRule(const XsltPolicyRule& r) : XsltPolicyNode(r) this->level = r.level; this->occurrence = r.occurrence; this->value = r.value; + if (r.source) + { + if (this->source) + delete this->source; + + this->source = new Source; + this->source->track_type = r.source->track_type; + this->source->field = r.source->field; + this->source->scope = r.source->scope; + this->source->occurrence = r.source->occurrence; + } } //--------------------------------------------------------------------------- @@ -118,6 +144,17 @@ int XsltPolicyRule::edit_policy_rule(const XsltPolicyRule* rule, std::string&) this->level = rule->level; this->occurrence = rule->occurrence; this->value = rule->value; + if (rule->source) + { + if (this->source) + delete this->source; + + this->source = new Source; + this->source->track_type = rule->source->track_type; + this->source->field = rule->source->field; + this->source->scope = rule->source->scope; + this->source->occurrence = rule->source->occurrence; + } return 0; } @@ -274,7 +311,7 @@ int XsltPolicy::run_over_siblings_nodes(xmlNodePtr node, bool is_root, XsltPolic { switch (node->type) { - case XML_TEXT_NODE: + case XML_TEXT_NODE: case XML_COMMENT_NODE: continue; default:; @@ -482,14 +519,62 @@ int XsltPolicy::parse_policy_rule(xmlNodePtr node, bool is_root, XsltPolicy* cur xmlFree(occurrence); } - //Get value - xmlChar *value = xmlNodeGetContent(node); - if (value) + //Get source + for (xmlNodePtr child = node->children; child; child = child->next) { - r->value = std::string((const char*)value); - xmlFree(value); + if (child->type == XML_ELEMENT_NODE && child->name && std::string((const char*)child->name) == "source") + { + if (r->source) + delete r->source; + + r->source = new XsltPolicyRule::Source(); + + //Get source trackType + xmlChar *track_type = xmlGetNoNsProp(child, (const unsigned char*)"tracktype"); + if (track_type) + { + r->source->track_type = std::string((const char*)track_type); + xmlFree(track_type); + } + + //Get source field + xmlChar *field = xmlGetNoNsProp(child, (const unsigned char*)"value"); + if (field) + { + r->source->field = std::string((const char*)field); + xmlFree(field); + } + + //Get source scope + xmlChar *scope = xmlGetNoNsProp(child, (const unsigned char*)"scope"); + if (scope) + { + r->source->scope = std::string((const char*)scope); + xmlFree(scope); + } + + //Get source occurrence + xmlChar *occurrence = xmlGetNoNsProp(child, (const unsigned char*)"occurrence"); + if (occurrence) + { + r->source->occurrence = std::string((const char*)occurrence); + xmlFree(occurrence); + } + break; + } } + //Get value + if (!r->source) + { + xmlChar *value = xmlNodeGetContent(node); + if (value) + { + r->value = std::string((const char*)value); + xmlFree(value); + } + } + return 0; } @@ -615,8 +700,36 @@ int XsltPolicy::create_node_rule_child(xmlNodePtr& node, XsltPolicyRule *current if (current->level.size()) xmlNewProp(node, (const xmlChar *)"level", (const xmlChar *)current->level.c_str()); - //value - if (current->value.size()) + //source or value + if (current->source) + { + xmlNodePtr child = xmlNewNode(NULL, (const xmlChar *)"source"); + if (!child) + { + error = "Cannot create the source children"; + return -1; + } + + //field + if (current->source->field.size()) + xmlNewProp(child, (const xmlChar *)"value", (const xmlChar *)current->source->field.c_str()); + + //track type + if (current->source->track_type.size()) + xmlNewProp(child, (const xmlChar *)"tracktype", (const xmlChar *)current->source->track_type.c_str()); + + + //scope + if (current->source->scope.size()) + xmlNewProp(child, (const xmlChar *)"scope", (const xmlChar *)current->source->scope.c_str()); + + //occurrence + if (current->source->occurrence.size()) + xmlNewProp(child, (const xmlChar *)"occurrence", (const xmlChar *)current->source->occurrence.c_str()); + + xmlAddChild(node, child); + } + else if (current->value.size()) xmlNodeSetContent(node, (const xmlChar*)current->value.c_str()); return 0; diff --git a/Source/Common/XsltPolicy.h b/Source/Common/XsltPolicy.h index 794b0188..7f1529ea 100644 --- a/Source/Common/XsltPolicy.h +++ b/Source/Common/XsltPolicy.h @@ -73,6 +73,13 @@ class XsltPolicyNode class XsltPolicyRule : public XsltPolicyNode { public: + struct Source { + std::string track_type; + std::string field; + std::string scope; + std::string occurrence; + }; + XsltPolicyRule(); virtual ~XsltPolicyRule(); XsltPolicyRule(const XsltPolicyRule*); @@ -88,6 +95,7 @@ class XsltPolicyRule : public XsltPolicyNode std::string scope; std::string level; std::string occurrence; + Source* source; std::string value; static size_t rule_id;