Camera: Add an XML parser for the XML metadata
Change-Id: Ie97893e82d6cae2cb7fa3853b326df1cf0f3ff18
diff --git a/camera/docs/metadata_validate.py b/camera/docs/metadata_validate.py
index 8dc6050..6c9c408 100755
--- a/camera/docs/metadata_validate.py
+++ b/camera/docs/metadata_validate.py
@@ -33,6 +33,7 @@
"""
from bs4 import BeautifulSoup
+from bs4 import Tag
import sys
@@ -90,6 +91,62 @@
else:
return None
+def find_all_child_tags(element, tag):
+ """
+ Finds all the children that are a Tag (as opposed to a NavigableString),
+ with a name of tag. This is useful to filter out the NavigableString out
+ of the children.
+
+ Args:
+ element: A BeautifulSoup Tag corresponding to an XML node
+ tag: A string representing the name of the tag
+
+ Returns:
+ A list of Tag instances
+
+ For example, given the following XML structure:
+ <enum> # This is the variable el
+ Hello world # NavigableString
+ <value>Apple</value> # this is the variale apple (Tag)
+ <value>Orange</value> # this is the variable orange (Tag)
+ Hello world again # NavigableString
+ </enum>
+
+ lst = find_all_child_tags(el, 'value')
+ # lst is [apple, orange]
+
+ """
+ matching_tags = [i for i in element.children if isinstance(i, Tag) and i.name == tag]
+ return matching_tags
+
+def find_child_tag(element, tag):
+ """
+ Finds the first child that is a Tag with the matching name.
+
+ Args:
+ element: a BeautifulSoup Tag
+ tag: A String representing the name of the tag
+
+ Returns:
+ An instance of a Tag, or None if there was no matches.
+
+ For example, given the following XML structure:
+ <enum> # This is the variable el
+ Hello world # NavigableString
+ <value>Apple</value> # this is the variale apple (Tag)
+ <value>Orange</value> # this is the variable orange (Tag)
+ Hello world again # NavigableString
+ </enum>
+
+ res = find_child_tag(el, 'value')
+ # res is apple
+ """
+ matching_tags = find_all_child_tags(element, tag)
+ if matching_tags:
+ return matching_tags[0]
+ else:
+ return None
+
def find_kind(element):
"""
Finds the kind Tag ancestor for an element.
@@ -150,10 +207,14 @@
return success
# All <entry> elements with container=$foo have a <$foo> child
+# If type="enum", <enum> tag is present
+# In <enum> for all <value id="$x">, $x is numeric
def validate_entries(soup):
"""
Validate all <entry> elements with the following rules:
* If there is a container="$foo" attribute, there is a <$foo> child
+ * If there is a type="enum" attribute, there is an <enum> child
+ * In the <enum> child, all <value id="$x"> have a numeric $x
Args:
soup - an instance of BeautifulSoup
@@ -175,8 +236,28 @@
%(fully_qualified_name(entry), find_kind(entry), \
entry_container, entry_container))
- return success
+ typ = entry.attrs.get('type')
+ if typ == 'enum':
+ if entry.enum is None:
+ validate_error(("Entry '%s' in kind '%s' is missing enum") \
+ % (fully_qualified_name(entry), find_kind(entry),
+ ))
+ if typ == 'enum' and entry.enum is not None:
+
+ for value in entry.enum.find_all('value'):
+ value_id = value.attrs.get('id')
+
+ if value_id is not None:
+ try:
+ id_int = int(value_id, 0) #autoguess base
+ except ValueError:
+ validate_error(("Entry '%s' has id '%s', which is not" + \
+ " numeric.") \
+ %(fully_qualified_name(entry), value_id))
+ success = False
+
+ return success
def validate_xml(file_name):
"""