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;