diff --git a/python/cpmf_uips_xaml/__version__.py b/python/cpmf_uips_xaml/__version__.py
index 4a05ed2..231f0d6 100644
--- a/python/cpmf_uips_xaml/__version__.py
+++ b/python/cpmf_uips_xaml/__version__.py
@@ -1,5 +1,5 @@
"""Version information for cpmf_uips_xaml package."""
-__version__ = "0.1.0"
+__version__ = "0.1.2"
__author__ = "Christian Prior-Mamulyan"
__description__ = "Standalone XAML workflow parser for automation projects"
diff --git a/python/cpmf_uips_xaml/stages/parsing/extractors.py b/python/cpmf_uips_xaml/stages/parsing/extractors.py
index 7f2abdd..d0265ab 100644
--- a/python/cpmf_uips_xaml/stages/parsing/extractors.py
+++ b/python/cpmf_uips_xaml/stages/parsing/extractors.py
@@ -20,6 +20,15 @@
if TYPE_CHECKING:
from .parser import XamlDialect
+# Tags that carry VB.NET / C# expressions as an ExpressionText attribute or element text,
+# used by the "child-element expression syntax" (Syntax B) introduced in newer UiPath Studio.
+_EXPR_ELEMENT_TAGS = frozenset({
+ "VisualBasicValue",
+ "VisualBasicReference",
+ "CSharpValue",
+ "CSharpReference",
+})
+
class ArgumentExtractor:
"""Extracts workflow arguments from x:Members section."""
@@ -669,6 +678,25 @@ def _extract_activity_arguments(self, element: ET.Element) -> dict[str, Any]:
clean_name = attr_name.split("}")[-1] if "}" in attr_name else attr_name
arguments[clean_name] = attr_value
+ # Child-element argument syntax:
+ #
+ for child in element:
+ child_tag = get_local_tag(child)
+ if "." in child_tag:
+ for param_child in child:
+ param_tag = get_local_tag(param_child)
+ if param_tag in ("InArgument", "OutArgument", "InOutArgument"):
+ for expr_elem in param_child:
+ expr_tag = get_local_tag(expr_elem)
+ if expr_tag in _EXPR_ELEMENT_TAGS:
+ expr_text = expr_elem.get("ExpressionText")
+ if expr_text:
+ existing = arguments.get(child_tag)
+ if existing is None:
+ arguments[child_tag] = [expr_text]
+ elif isinstance(existing, list):
+ existing.append(expr_text)
+
return arguments
def _extract_visible_properties(self, element: ET.Element) -> dict[str, Any]:
@@ -759,6 +787,18 @@ def _extract_business_logic_expressions(self, element: ET.Element) -> list[str]:
extracted_expressions = self.activity_utils.extract_expressions_from_text(element.text)
expressions.extend(extracted_expressions)
+ # Child-element expression syntax:
+ # ExpressionText contains the raw VB.NET/C# expression (no brackets), so add directly.
+ for descendant in element.iter():
+ tag = descendant.tag.split("}")[-1] if "}" in descendant.tag else descendant.tag
+ if tag in _EXPR_ELEMENT_TAGS:
+ expr_text = descendant.get("ExpressionText")
+ if expr_text:
+ expressions.append(expr_text)
+ # Older serializations may embed the expression as element text
+ if descendant.text and descendant.text.strip():
+ expressions.append(descendant.text.strip())
+
return list(set(expressions)) # Remove duplicates
def _extract_variable_references(
diff --git a/python/tests/unit/test_extractors.py b/python/tests/unit/test_extractors.py
index 5dce620..35df030 100644
--- a/python/tests/unit/test_extractors.py
+++ b/python/tests/unit/test_extractors.py
@@ -1127,6 +1127,98 @@ def test_extract_business_logic_expressions(self, xaml_with_expressions):
if len(expressions) > 0:
assert any("[" in expr or "(" in expr for expr in expressions)
+ def test_extract_expressions_from_visual_basic_value_element(self):
+ """VisualBasicValue ExpressionText is extracted as an expression."""
+ xaml = """
+
+
+
+
+
+
+"""
+ root = parse_xaml_string(xaml)
+ extractor = create_activity_extractor()
+
+ expressions = extractor._extract_business_logic_expressions(root)
+
+ assert "lookupData" in expressions
+
+ def test_extract_expressions_from_visual_basic_reference_element(self):
+ """VisualBasicReference ExpressionText contributes to expressions."""
+ xaml = """
+
+
+
+
+
+
+"""
+ root = parse_xaml_string(xaml)
+ extractor = create_activity_extractor()
+
+ expressions = extractor._extract_business_logic_expressions(root)
+
+ assert "myVar" in expressions
+
+ def test_mixed_bracket_and_element_syntax_same_activity(self):
+ """Activities using both [expr] attributes and VisualBasicValue children are both extracted."""
+ xaml = """
+
+
+
+
+
+
+"""
+ root = parse_xaml_string(xaml)
+ extractor = create_activity_extractor()
+
+ expressions = extractor._extract_business_logic_expressions(root)
+
+ assert "lookupData" in expressions
+ # Bracket syntax strips delimiters: [servicePoint] → servicePoint
+ assert "servicePoint" in expressions
+
+ def test_extract_arguments_from_child_element_syntax(self):
+ """_extract_activity_arguments captures ExpressionText from InArgument children."""
+ xaml = """
+
+
+
+
+
+
+
+
+
+"""
+ root = parse_xaml_string(xaml)
+ extractor = create_activity_extractor()
+
+ arguments = extractor._extract_activity_arguments(root)
+
+ assert "InvokeMethod.Parameters" in arguments
+ params = arguments["InvokeMethod.Parameters"]
+ assert "in_LookupData" in params
+ assert "in_RulesString" in params
+
# ============================================================================
# Test ActivityExtractor - Activity Instance Extraction (ADR-009)