# 処理モデル

#### 4.9.12 処理モデル

テーブルは、座標 (x, y) を持つスロットの 2 次元グリッド上に並べられるセルから構成されます。グリッドは有限であり、空か、または、1 つ以上のスロットを持ちます。グリッドが 1 つ以上のスロットを持つなら、その x 座標は常に 0 ≤ y < yheight の範囲になり、y 座標は常に 0 ≤ y < yheight の範囲になります。 xwidthyheight の一方または両方が 0 なら、そのテーブルは空です（スロットを一つも持ちません）。テーブルは `table` 要素に相当します。

セルは、スロット (cellx, celly) に固定されたスロットのセットで、固有の widthheight を持ち、その範囲は、cellx ≤ x < cellx+width かつ celly ≤ y < celly+height となる (x, y) を座標に持つすべてのスロットに及びます。セルは、データセル、または、ヘッダーセルのいずれかになります。データセルは `td` 要素に相当し、ヘッダーセルは `th` 要素に相当します。どちらのタイプのセルも、0 個以上の関連ヘッダーセルを持つことができます。

エラーではありますが、2 つのセルが同じスロットを占有することが起こりえます。

は、特定の値 y に対して、 x=0 から x=xwidth-1 までのスロット一式です。行は、通常は、`tr` 要素に相当します。しかし、行グループは、複数の行に範囲が及ぶセルを含む場合には、最後にいくつかの暗黙のを持つことができます。

は、特定の値 x に対して、 y=0 から y=yheight-1 までのスロット一式です。列は `col` 要素に対応付けることができます。`col` 要素がない場合、列は暗黙的になります。

セルは、2 つ以上の行グループに範囲が及ぶことはできません。しかし、セルは複数の列グループに入ることは可能です。1 つのセルの一部になるスロットはいずれも、0 か 1 個の行グループ、かつ、0 個以上の列グループの一部になります。

セル行グループ列グループに加え、テーブルは、それに関連付けられた `caption` 要素を持つことができます。これはテーブルに見出しやキャプションを与えます。

テーブルモデルエラーとは、`table` 要素とその子孫によって表されるデータのエラーのことです。ドキュメントは、テーブルモデルエラーを持ってはいけません。

##### 4.9.12.1 テーブルの形成

To determine which elements correspond to which slots in a table associated with a `table` element, to determine the dimensions of the table (xwidth and yheight), and to determine if there are any table model errors, user agents must use the following algorithm:

1. Let xwidth be zero.

2. Let yheight be zero.

3. Let pending `tfoot` elements be a list of `tfoot` elements, initially empty.

4. Let the table be the table represented by the `table` element. The xwidth and yheight variables give the table's dimensions. The table is initially empty.

5. If the `table` element has no children elements, then return the table (which will be empty), and abort these steps.

6. Associate the first `caption` element child of the `table` element with the table. If there are no such children, then it has no associated `caption` element.

7. Let the current element be the first element child of the `table` element.

If a step in this algorithm ever requires the current element to be advanced to the next child of the `table` when there is no such next child, then the user agent must jump to the step labeled end, near the end of this algorithm.

8. While the current element is not one of the following elements, advance the current element to the next child of the `table`:

• `colgroup`
• `thead`
• `tbody`
• `tfoot`
• `tr`
9. If the current element is a `colgroup`, follow these substeps:

1. Column groups: Process the current element according to the appropriate case below:

If the current element has any `col` element children

1. Let xstart have the value of xwidth.

2. Let the current column be the first `col` element child of the `colgroup` element.

3. Columns: If the current column `col` element has a `span` attribute, then parse its value using the rules for parsing non-negative integers.

If the result of parsing the value is not an error or zero, then let span be that value.

Otherwise, if the `col` element has no `span` attribute, or if trying to parse the attribute's value resulted in an error or zero, then let span be 1.

4. Increase xwidth by span.

5. Let the last span columns in the table correspond to the current column `col` element.

6. If current column is not the last `col` element child of the `colgroup` element, then let the current column be the next `col` element child of the `colgroup` element, and return to the step labeled columns.

7. Let all the last columns in the table from x=xstart to x=xwidth-1 form a new column group, anchored at the slot (xstart, 0), with width xwidth-xstart, corresponding to the `colgroup` element.

If the current element has no `col` element children
1. If the `colgroup` element has a `span` attribute, then parse its value using the rules for parsing non-negative integers.

If the result of parsing the value is not an error or zero, then let span be that value.

Otherwise, if the `colgroup` element has no `span` attribute, or if trying to parse the attribute's value resulted in an error or zero, then let span be 1.

2. Increase xwidth by span.

3. Let the last span columns in the table form a new column group, anchored at the slot (xwidth-span, 0), with width span, corresponding to the `colgroup` element.

2. Advance the current element to the next child of the `table`.

3. While the current element is not one of the following elements, advance the current element to the next child of the `table`:

• `colgroup`
• `thead`
• `tbody`
• `tfoot`
• `tr`
4. If the current element is a `colgroup` element, jump to the step labeled column groups above.

10. Let ycurrent be zero.

11. Let the list of downward-growing cells be an empty list.

12. Rows: While the current element is not one of the following elements, advance the current element to the next child of the `table`:

• `thead`
• `tbody`
• `tfoot`
• `tr`
13. If the current element is a `tr`, then run the algorithm for processing rows, advance the current element to the next child of the `table`, and return to the step labeled rows.

14. Run the algorithm for ending a row group.

15. If the current element is a `tfoot`, then add that element to the list of pending `tfoot` elements, advance the current element to the next child of the `table`, and return to the step labeled rows.

16. The current element is either a `thead` or a `tbody`.

17. Advance the current element to the next child of the `table`.

19. End: For each `tfoot` element in the list of pending `tfoot` elements, in tree order, run the algorithm for processing row groups.

20. If there exists a row or column in the table containing only slots that do not have a cell anchored to them, then this is a table model error.

21. Return the table.

The algorithm for processing row groups, which is invoked by the set of steps above for processing `thead`, `tbody`, and `tfoot` elements, is:

1. Let ystart have the value of yheight.

2. For each `tr` element that is a child of the element being processed, in tree order, run the algorithm for processing rows.

3. If yheight > ystart, then let all the last rows in the table from y=ystart to y=yheight-1 form a new row group, anchored at the slot with coordinate (0, ystart), with height yheight-ystart, corresponding to the element being processed.

4. Run the algorithm for ending a row group.

The algorithm for ending a row group, which is invoked by the set of steps above when starting and ending a block of rows, is:

1. While ycurrent is less than yheight, follow these steps:

1. Increase ycurrent by 1.

2. Empty the list of downward-growing cells.

The algorithm for processing rows, which is invoked by the set of steps above for processing `tr` elements, is:

1. If yheight is equal to ycurrent, then increase yheight by 1. (ycurrent is never greater than yheight.)

2. Let xcurrent be 0.

3. If the `tr` element being processed has no `td` or `th` element children, then increase ycurrent by 1, abort this set of steps, and return to the algorithm above.

4. Let current cell be the first `td` or `th` element child in the `tr` element being processed.

5. Cells: While xcurrent is less than xwidth and the slot with coordinate (xcurrent, ycurrent) already has a cell assigned to it, increase xcurrent by 1.

6. If xcurrent is equal to xwidth, increase xwidth by 1. (xcurrent is never greater than xwidth.)

7. If the current cell has a `colspan` attribute, then parse that attribute's value, and let colspan be the result.

If parsing that value failed, or returned zero, or if the attribute is absent, then let colspan be 1, instead.

8. If the current cell has a `rowspan` attribute, then parse that attribute's value, and let rowspan be the result.

If parsing that value failed or if the attribute is absent, then let rowspan be 1, instead.

9. If rowspan is zero and the `table` element's `Document` is not set to quirks mode, then let cell grows downward be true, and set rowspan to 1. Otherwise, let cell grows downward be false.

10. If xwidth < xcurrent+colspan, then let xwidth be xcurrent+colspan.

11. If yheight < ycurrent+rowspan, then let yheight be ycurrent+rowspan.

12. Let the slots with coordinates (x, y) such that xcurrent ≤ x < xcurrent+colspan and ycurrent ≤ y < ycurrent+rowspan be covered by a new cell c, anchored at (xcurrent, ycurrent), which has width colspan and height rowspan, corresponding to the current cell element.

If the current cell element is a `th` element, let this new cell c be a header cell; otherwise, let it be a data cell.

To establish which header cells apply to the current cell element, use the algorithm for assigning header cells described in the next section.

If any of the slots involved already had a cell covering them, then this is a table model error. Those slots now have two cells overlapping.

13. If cell grows downward is true, then add the tuple {c, xcurrent, colspan} to the list of downward-growing cells.

14. Increase xcurrent by colspan.

15. If current cell is the last `td` or `th` element child in the `tr` element being processed, then increase ycurrent by 1, abort this set of steps, and return to the algorithm above.

16. Let current cell be the next `td` or `th` element child in the `tr` element being processed.

When the algorithms above require the user agent to run the algorithm for growing downward-growing cells, the user agent must, for each {cell, cellx, width} tuple in the list of downward-growing cells, if any, extend the cell cell so that it also covers the slots with coordinates (x, ycurrent), where cellx ≤ x < cellx+width.

##### 4.9.12.2 データセルとヘッダーセルの間の関係性の形成

Each cell can be assigned zero or more header cells. The algorithm for assigning header cells to a cell principal cell is as follows.

1. Let header list be an empty list of cells.

2. Let (principalx, principaly) be the coordinate of the slot to which the principal cell is anchored.

3. If the principal cell has a `headers` attribute specified
1. Take the value of the principal cell's `headers` attribute and split it on spaces, letting id list be the list of tokens obtained.

2. For each token in the id list, if the first element in the `Document` with an ID equal to the token is a cell in the same table, and that cell is not the principal cell, then add that cell to header list.

If principal cell does not have a `headers` attribute specified
1. Let principalwidth be the width of the principal cell.

2. Let principalheight be the height of the principal cell.

3. For each value of y from principaly to principaly+principalheight-1, run the internal algorithm for scanning and assigning header cells, with the principal cell, the header list, the initial coordinate (principalx,y), and the increments Δx=−1 and Δy=0.

4. For each value of x from principalx to principalx+principalwidth-1, run the internal algorithm for scanning and assigning header cells, with the principal cell, the header list, the initial coordinate (x,principaly), and the increments Δx=0 and Δy=−1.

5. If the principal cell is anchored in a row group, then add all header cells that are row group headers and are anchored in the same row group with an x-coordinate less than or equal to principalx+principalwidth-1 and a y-coordinate less than or equal to principaly+principalheight-1 to header list.

6. If the principal cell is anchored in a column group, then add all header cells that are column group headers and are anchored in the same column group with an x-coordinate less than or equal to principalx+principalwidth-1 and a y-coordinate less than or equal to principaly+principalheight-1 to header list.

4. Remove all the empty cells from the header list.

5. Remove any duplicates from the header list.

6. Remove principal cell from the header list if it is there.

7. Assign the headers in the header list to the principal cell.

The internal algorithm for scanning and assigning header cells, given a principal cell, a header list, an initial coordinate (initialx, initialy), and Δx and Δy increments, is as follows:

1. Let x equal initialx.

2. Let y equal initialy.

3. Let opaque headers be an empty list of cells.

4. If principal cell is a header cell

Let in header block be true, and let headers from current header block be a list of cells containing just the principal cell.

Otherwise

Let in header block be false and let headers from current header block be an empty list of cells.

5. Loop: Increment x by Δx; increment y by Δy.

For each invocation of this algorithm, one of Δx and Δy will be −1, and the other will be 0.

6. If either x or y is less than 0, then abort this internal algorithm.

7. If there is no cell covering slot (x, y), or if there is more than one cell covering slot (x, y), return to the substep labeled loop.

8. Let current cell be the cell covering slot (x, y).

9. If current cell is a header cell
1. Set in header block to true.

3. Let blocked be false.

4. If Δx is 0

If there are any cells in the opaque headers list anchored with the same x-coordinate as the current cell, and with the same width as current cell, then let blocked be true.

If the current cell is not a column header, then let blocked be true.

If Δy is 0

If there are any cells in the opaque headers list anchored with the same y-coordinate as the current cell, and with the same height as current cell, then let blocked be true.

If the current cell is not a row header, then let blocked be true.

5. If blocked is false, then add the current cell to the headers list.

If current cell is a data cell and in header block is true

A header cell anchored at the slot with coordinate (x, y) with width width and height height is said to be a column header if any of the following conditions are true:

• The cell's `scope` attribute is in the column state, or
• The cell's `scope` attribute is in the auto state, and there are no data cells in any of the cells covering slots with y-coordinates y .. y+height-1.

A header cell anchored at the slot with coordinate (x, y) with width width and height height is said to be a row header if any of the following conditions are true:

• The cell's `scope` attribute is in the row state, or
• The cell's `scope` attribute is in the auto state, the cell is not a column header, and there are no data cells in any of the cells covering slots with x-coordinates x .. x+width-1.

A header cell is said to be a column group header if its `scope` attribute is in the column group state.

A header cell is said to be a row group header if its `scope` attribute is in the row group state.

A cell is said to be an empty cell if it contains no elements and its text content, if any, consists only of White_Space characters.