> ## Documentation Index
> Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Objects & Attributes

> Manage structured extracted data inside Kodexa documents using data objects and data attributes, the structured data layer that sits on top of KDDB nodes.

Data objects and data attributes provide a structured data layer within KDDB documents. Data objects represent extracted entities (e.g., an invoice line item, a person, an address), while data attributes store the individual fields and values associated with those entities.

## Overview

The data layer is separate from the content node tree and designed for storing extraction results:

* **Data Objects**: Entities with parent-child relationships and taxonomy references
* **Data Attributes**: Typed fields attached to data objects (string, decimal, date, boolean)
* **Confidence Scores**: Each attribute can have an extraction confidence score
* **Taxonomy Integration**: Objects and attributes can reference taxonomy definitions

## Data Objects

### Creating Data Objects

<CodeGroup>
  ```python Python theme={null}
  from kodexa_document import Document
  from kodexa_document.accessors import DataObjectInput

  with Document() as doc:
      root = doc.create_node("document", "Invoice #12345")
      doc.content_node = root

      # Create a root data object
      invoice = doc.data_objects.create(DataObjectInput(
          path="/invoice"
      ))
      print(f"Created data object: {invoice}")

      # Create child data objects
      line_item_1 = doc.data_objects.create(DataObjectInput(
          parent_id=invoice['id'],
          path="/invoice/line-item"
      ))

      line_item_2 = doc.data_objects.create(DataObjectInput(
          parent_id=invoice['id'],
          path="/invoice/line-item"
      ))
  ```

  ```typescript TypeScript theme={null}
  import { Kodexa } from '@kodexa-ai/document-wasm-ts';

  async function createDataObjects() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      // Create a root data object
      const invoice = await doc.dataObjects.create({
        path: '/invoice'
      });
      console.log(`Created data object: ${invoice.id}`);

      // Create child data objects
      const lineItem1 = await doc.dataObjects.create({
        parentId: invoice.id,
        path: '/invoice/line-item'
      });

      const lineItem2 = await doc.dataObjects.create({
        parentId: invoice.id,
        path: '/invoice/line-item'
      });
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### Retrieving Data Objects

<CodeGroup>
  ```python Python theme={null}
  with Document.from_kddb("processed.kddb") as doc:
      # Get all data objects
      all_objects = doc.data_objects.get_all()
      print(f"Total data objects: {len(all_objects)}")

      # Get root-level objects only
      roots = doc.data_objects.get_roots()

      # Get children of a specific object
      for root_obj in roots:
          children = doc.data_objects.get_children(root_obj['groupUuid'])
          print(f"Object {root_obj['path']} has {len(children)} children")

      # Get by UUID
      obj = doc.data_objects.get_by_uuid("some-uuid")

      # Get by group UUID
      group = doc.data_objects.get_by_group_uuid("group-uuid")
  ```

  ```typescript TypeScript theme={null}
  async function retrieveDataObjects() {
    await Kodexa.init();
    const doc = await Kodexa.fromBlob(kddbBlob);

    try {
      // Get all data objects
      const allObjects = await doc.dataObjects.getAll();
      console.log(`Total data objects: ${allObjects.length}`);

      // Get root-level objects only
      const roots = await doc.dataObjects.getRoots();

      // Get children of a specific object
      for (const rootObj of roots) {
        const children = await doc.dataObjects.getChildren(rootObj.id);
        console.log(`Object ${rootObj.path} has ${children.length} children`);
      }

      // Get by ID
      const obj = await doc.dataObjects.getByID(1);

      // Get by taxonomy reference
      const byTaxonomy = await doc.dataObjects.getByTaxonomyRef('acme/invoice:1.0.0');

      // Get by path
      const byPath = await doc.dataObjects.getByPath('/invoice/line-item');
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### Updating and Deleting Data Objects

<CodeGroup>
  ```python Python theme={null}
  with Document.from_kddb("processed.kddb") as doc:
      # Update a data object
      doc.data_objects.update("some-uuid", DataObjectInput(
          path="/invoice/updated-path"
      ))

      # Delete a data object
      doc.data_objects.delete("some-uuid")
  ```

  ```typescript TypeScript theme={null}
  async function modifyDataObjects() {
    await Kodexa.init();
    const doc = await Kodexa.fromBlob(kddbBlob);

    try {
      // Update a data object
      await doc.dataObjects.update(1, { path: '/invoice/updated-path' });

      // Delete a data object
      await doc.dataObjects.delete(1);

      // Move a data object to a new parent
      await doc.dataObjects.move(2, 5, '/new-parent/child');

      // Copy a data object (with attributes)
      await doc.dataObjects.copy(1, 5, '/new-parent/copied', true);
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

## Data Attributes

### Creating Data Attributes

<CodeGroup>
  ```python Python theme={null}
  from kodexa_document.accessors import DataAttributeInput

  with Document() as doc:
      root = doc.create_node("document", "Invoice")
      doc.content_node = root

      # Create a data object first
      invoice = doc.data_objects.create(DataObjectInput(path="/invoice"))

      # Add string attribute
      doc.data_attributes.create(invoice['id'], DataAttributeInput(
          tag="vendor-name",
          string_value="Acme Corp",
          confidence=0.95,
          owner_uri="model://kodexa/invoice-extractor:1.0.0"
      ))

      # Add decimal attribute
      doc.data_attributes.create(invoice['id'], DataAttributeInput(
          tag="total-amount",
          decimal_value=1234.56,
          confidence=0.92
      ))

      # Add date attribute
      doc.data_attributes.create(invoice['id'], DataAttributeInput(
          tag="invoice-date",
          date_value="2024-01-15",
          confidence=0.98
      ))

      # Add boolean attribute
      doc.data_attributes.create(invoice['id'], DataAttributeInput(
          tag="is-paid",
          boolean_value=False,
          confidence=1.0
      ))
  ```

  ```typescript TypeScript theme={null}
  async function createDataAttributes() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      // Create a data object first
      const invoice = await doc.dataObjects.create({ path: '/invoice' });

      // Add string attribute
      await doc.dataAttributes.create(invoice.id, {
        tag: 'vendor-name',
        stringValue: 'Acme Corp',
        confidence: 0.95,
        ownerUri: 'model://kodexa/invoice-extractor:1.0.0'
      });

      // Add decimal attribute
      await doc.dataAttributes.create(invoice.id, {
        tag: 'total-amount',
        decimalValue: 1234.56,
        confidence: 0.92
      });

      // Add date attribute
      await doc.dataAttributes.create(invoice.id, {
        tag: 'invoice-date',
        dateValue: '2024-01-15',
        confidence: 0.98
      });

      // Add boolean attribute
      await doc.dataAttributes.create(invoice.id, {
        tag: 'is-paid',
        booleanValue: false,
        confidence: 1.0
      });
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### Retrieving Data Attributes

<CodeGroup>
  ```python Python theme={null}
  with Document.from_kddb("processed.kddb") as doc:
      # Get all data objects
      objects = doc.data_objects.get_all()

      for obj in objects:
          # Get attributes for a data object
          attrs = doc.data_attributes.get_for_data_object(obj['id'])

          for attr in attrs:
              print(f"  {attr['tag']}: {attr.get('stringValue') or attr.get('decimalValue')}")
              print(f"    Confidence: {attr.get('confidence')}")

      # Get a specific attribute by ID
      attr = doc.data_attributes.get_by_id(1)
  ```

  ```typescript TypeScript theme={null}
  async function retrieveDataAttributes() {
    await Kodexa.init();
    const doc = await Kodexa.fromBlob(kddbBlob);

    try {
      // Get all data objects
      const objects = await doc.dataObjects.getAll();

      for (const obj of objects) {
        // Get attributes for a data object
        const attrs = await doc.dataAttributes.getForDataObject(obj.id);

        for (const attr of attrs) {
          const value = doc.dataAttributes.getTypedValue(attr);
          console.log(`  ${attr.tag}: ${value}`);
          console.log(`    Confidence: ${attr.confidence}`);
        }
      }

      // Get by tag name
      const vendorAttrs = await doc.dataAttributes.getByTag('vendor-name');

      // Get by path
      const pathAttrs = await doc.dataAttributes.getByPath('/invoice/vendor-name');

      // Get a specific attribute by ID
      const attr = await doc.dataAttributes.getByID(1);
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

### Updating Data Attributes

<CodeGroup>
  ```python Python theme={null}
  with Document.from_kddb("processed.kddb") as doc:
      # Update an attribute
      doc.data_attributes.update(1, DataAttributeInput(
          string_value="Updated Vendor Name",
          confidence=0.99
      ))

      # Delete an attribute
      doc.data_attributes.delete(1)
  ```

  ```typescript TypeScript theme={null}
  async function updateDataAttributes() {
    await Kodexa.init();
    const doc = await Kodexa.fromBlob(kddbBlob);

    try {
      // Update an attribute value
      await doc.dataAttributes.setValue(1, 'Updated Vendor Name');

      // Update confidence
      await doc.dataAttributes.setConfidence(1, 0.99);

      // Add a feature to an attribute
      await doc.dataAttributes.addFeature(1, 'source', 'manual-correction');

      // Delete an attribute
      await doc.dataAttributes.delete(1);
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>

## DataObjectInput Reference

| Field    | Python         | TypeScript    | Description                        |
| -------- | -------------- | ------------- | ---------------------------------- |
| Parent   | `parent_id`    | `parentId`    | ID of the parent data object       |
| Taxonomy | `taxonomy_ref` | `taxonomyRef` | Reference to a taxonomy definition |
| Path     | `path`         | `path`        | Hierarchical path identifier       |

## DataAttributeInput Reference

| Field         | Python             | TypeScript       | Description                              |
| ------------- | ------------------ | ---------------- | ---------------------------------------- |
| Tag           | `tag`              | `tag`            | Tag name linking to the content node tag |
| Tag ID        | `tag_id`           | `tagId`          | Direct tag ID reference                  |
| Value         | `value`            | `value`          | Generic value                            |
| String Value  | `string_value`     | `stringValue`    | String-typed value                       |
| Decimal Value | `decimal_value`    | `decimalValue`   | Numeric value                            |
| Date Value    | `date_value`       | `dateValue`      | Date string value                        |
| Boolean Value | `boolean_value`    | `booleanValue`   | Boolean value                            |
| Confidence    | `confidence`       | `confidence`     | Extraction confidence (0-1)              |
| Type          | `type_at_creation` | `typeAtCreation` | Type classification                      |
| Path          | `path`             | `path`           | Hierarchical path identifier             |
| Owner URI     | `owner_uri`        | `ownerUri`       | Source identifier (e.g., model URI)      |
| Data Features | `data_features`    | `dataFeatures`   | Additional metadata dictionary           |

## Complete Example

<CodeGroup>
  ```python Python theme={null}
  from kodexa_document import Document
  from kodexa_document.accessors import DataObjectInput, DataAttributeInput

  def extract_invoice_data():
      with Document() as doc:
          root = doc.create_node("document", "Invoice #12345")
          doc.content_node = root

          # Create the invoice data object
          invoice = doc.data_objects.create(DataObjectInput(
              path="/invoice",
              taxonomy_ref="acme/invoice:1.0.0"
          ))

          # Add header attributes
          doc.data_attributes.create(invoice['id'], DataAttributeInput(
              tag="invoice-number",
              string_value="INV-2024-001",
              confidence=0.99
          ))
          doc.data_attributes.create(invoice['id'], DataAttributeInput(
              tag="vendor-name",
              string_value="Acme Corp",
              confidence=0.95
          ))
          doc.data_attributes.create(invoice['id'], DataAttributeInput(
              tag="invoice-date",
              date_value="2024-01-15",
              confidence=0.98
          ))

          # Create line items
          items = [
              ("Widget A", 100.00),
              ("Widget B", 250.00),
              ("Service Fee", 50.00)
          ]

          for desc, amount in items:
              line_item = doc.data_objects.create(DataObjectInput(
                  parent_id=invoice['id'],
                  path="/invoice/line-item"
              ))
              doc.data_attributes.create(line_item['id'], DataAttributeInput(
                  tag="description",
                  string_value=desc,
                  confidence=0.92
              ))
              doc.data_attributes.create(line_item['id'], DataAttributeInput(
                  tag="amount",
                  decimal_value=amount,
                  confidence=0.90
              ))

          # Add total
          doc.data_attributes.create(invoice['id'], DataAttributeInput(
              tag="total-amount",
              decimal_value=400.00,
              confidence=0.95
          ))

          # Query the results
          roots = doc.data_objects.get_roots()
          for obj in roots:
              attrs = doc.data_attributes.get_for_data_object(obj['id'])
              print(f"Data Object: {obj['path']}")
              for attr in attrs:
                  print(f"  {attr['tag']}: {attr.get('stringValue') or attr.get('decimalValue')}")

          doc.save("extracted_invoice.kddb")
  ```

  ```typescript TypeScript theme={null}
  import { Kodexa } from '@kodexa-ai/document-wasm-ts';

  async function extractInvoiceData() {
    await Kodexa.init();
    const doc = await Kodexa.createDocument();

    try {
      const root = await doc.createNode('document');
      await root.setContent('Invoice #12345');

      // Create the invoice data object
      const invoice = await doc.dataObjects.create({
        path: '/invoice',
        taxonomyRef: 'acme/invoice:1.0.0'
      });

      // Add header attributes
      await doc.dataAttributes.create(invoice.id, {
        tag: 'invoice-number',
        stringValue: 'INV-2024-001',
        confidence: 0.99
      });
      await doc.dataAttributes.create(invoice.id, {
        tag: 'vendor-name',
        stringValue: 'Acme Corp',
        confidence: 0.95
      });
      await doc.dataAttributes.create(invoice.id, {
        tag: 'invoice-date',
        dateValue: '2024-01-15',
        confidence: 0.98
      });

      // Create line items
      const items = [
        { desc: 'Widget A', amount: 100.00 },
        { desc: 'Widget B', amount: 250.00 },
        { desc: 'Service Fee', amount: 50.00 }
      ];

      for (const { desc, amount } of items) {
        const lineItem = await doc.dataObjects.create({
          parentId: invoice.id,
          path: '/invoice/line-item'
        });
        await doc.dataAttributes.create(lineItem.id, {
          tag: 'description',
          stringValue: desc,
          confidence: 0.92
        });
        await doc.dataAttributes.create(lineItem.id, {
          tag: 'amount',
          decimalValue: amount,
          confidence: 0.90
        });
      }

      // Add total
      await doc.dataAttributes.create(invoice.id, {
        tag: 'total-amount',
        decimalValue: 400.00,
        confidence: 0.95
      });

      // Query the results
      const roots = await doc.dataObjects.getRoots();
      for (const obj of roots) {
        const attrs = await doc.dataAttributes.getForDataObject(obj.id);
        console.log(`Data Object: ${obj.path}`);
        for (const attr of attrs) {
          const value = doc.dataAttributes.getTypedValue(attr);
          console.log(`  ${attr.tag}: ${value}`);
        }
      }

      const blob = await doc.toBlob();
      console.log('Document exported successfully');
    } finally {
      doc.dispose();
    }
  }
  ```
</CodeGroup>
