Make Table.To_Xml return a XML_Document (#9263)

As part of the XML improvements it makes more sense for Table.To_Xml to return a XML_Document.
This commit is contained in:
AdRiley 2024-03-04 15:19:20 +00:00 committed by GitHub
parent 6f4963d7d1
commit 8b889f0977
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 53 deletions

View File

@ -2649,7 +2649,7 @@ type Table
to_csv self = Text.from self (Delimited_Format.Delimited delimiter=",") to_csv self = Text.from self (Delimited_Format.Delimited delimiter=",")
## GROUP Standard.Base.Conversions ## GROUP Standard.Base.Conversions
Returns a string containing an XML representation of the table. Returns an `XML_Document` representation of the table.
Arguments: Arguments:
- element_columns: Columns to be used as elements in the XML. - element_columns: Columns to be used as elements in the XML.
- attribute_columns: Columns to be used as attributes in the XML. - attribute_columns: Columns to be used as attributes in the XML.
@ -2691,7 +2691,7 @@ type Table
@element_columns Widget_Helpers.make_column_name_vector_selector @element_columns Widget_Helpers.make_column_name_vector_selector
@attribute_columns Widget_Helpers.make_column_name_vector_selector @attribute_columns Widget_Helpers.make_column_name_vector_selector
@value_column Widget_Helpers.make_column_name_selector @value_column Widget_Helpers.make_column_name_selector
to_xml self (element_columns : (Vector (Integer | Text | Regex) | Text | Integer | Regex) = self.column_names) (attribute_columns : (Vector (Integer | Text | Regex) | Text | Integer | Regex) = []) (value_column : Text | Integer | Nothing = Nothing) (root_name : Text = "Table") (row_name : Text = "Row") (on_problems : Problem_Behavior = Report_Warning) -> Text = to_xml self (element_columns : (Vector (Integer | Text | Regex) | Text | Integer | Regex) = self.column_names) (attribute_columns : (Vector (Integer | Text | Regex) | Text | Integer | Regex) = []) (value_column : Text | Integer | Nothing = Nothing) (root_name : Text = "Table") (row_name : Text = "Row") (on_problems : Problem_Behavior = Report_Warning) -> XML_Document =
columns_helper = self.columns_helper columns_helper = self.columns_helper
problem_builder = Problem_Builder.new error_on_missing_columns=True problem_builder = Problem_Builder.new error_on_missing_columns=True
resolved_element_columns = columns_helper.select_columns_helper element_columns Case_Sensitivity.Default False problem_builder resolved_element_columns = columns_helper.select_columns_helper element_columns Case_Sensitivity.Default False problem_builder
@ -2707,7 +2707,7 @@ type Table
if unused_columns.length > 0 then problem_builder.report_other_warning (Unexpected_Extra_Columns.Warning unused_columns) if unused_columns.length > 0 then problem_builder.report_other_warning (Unexpected_Extra_Columns.Warning unused_columns)
problem_builder.attach_problems_before on_problems <| problem_builder.attach_problems_before on_problems <|
Java_TableToXml.to_xml self.row_count java_element_columns java_attribute_column java_value_column root_name row_name XML_Document.Value (Java_TableToXml.to_xml self.row_count java_element_columns java_attribute_column java_value_column root_name row_name)
## PRIVATE ## PRIVATE
columns_helper : Table_Column_Helper columns_helper : Table_Column_Helper

View File

@ -10,12 +10,10 @@ import org.graalvm.polyglot.Context;
import org.w3c.dom.DOMException; import org.w3c.dom.DOMException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
public class TableToXml { public class TableToXml {
public static String to_xml( public static Document to_xml(
int rowCount, int rowCount,
Column[] element_columns, Column[] element_columns,
Column[] attribute_columns, Column[] attribute_columns,
@ -56,16 +54,7 @@ public class TableToXml {
context.safepoint(); context.safepoint();
} }
return convert_to_string(doc); return doc;
}
private static String convert_to_string(Document doc) throws XmlException {
DOMImplementationLS domImplementation = (DOMImplementationLS) doc.getImplementation();
LSSerializer lsSerializer = domImplementation.createLSSerializer();
lsSerializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
lsSerializer.getDomConfig().setParameter("xml-declaration", false);
lsSerializer.setNewLine("\n");
return lsSerializer.writeToString(doc);
} }
private static void get_set_attribute( private static void get_set_attribute(

View File

@ -4,8 +4,9 @@ from Standard.Test import all
from Standard.Table.Errors import all from Standard.Table.Errors import all
import Standard.Base.Errors.Common.Type_Error import Standard.Base.Errors.Common.Type_Error
# pretty printed xml actually makes the tests less pretty ## Pretty xml makes the tests easier to read,
# so all but one tests depretty the xml before comparing so this function allows to convert a pretty-formatted expected XML value
into a raw value that can be compared with the generated XML.
depretty xmlText = depretty xmlText =
xmlText.replace (Regex.compile "\n\s*") "" xmlText.replace (Regex.compile "\n\s*") ""
@ -36,7 +37,7 @@ add_specs suite_builder =
t = data.table . take 0 t = data.table . take 0
r = t.to_xml r = t.to_xml
e = "<Table/>" e = "<Table/>"
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "if no columns are specified all fields become child elements" <| group_builder.specify "if no columns are specified all fields become child elements" <|
t = data.table . select_columns ['Title', 'Year'] t = data.table . select_columns ['Title', 'Year']
r = t.to_xml r = t.to_xml
@ -59,7 +60,7 @@ add_specs suite_builder =
<Year>1939</Year> <Year>1939</Year>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Single column as element" <| group_builder.specify "Single column as element" <|
t = data.table . take 4 t = data.table . take 4
r = t.to_xml ["Year"] r = t.to_xml ["Year"]
@ -78,7 +79,7 @@ add_specs suite_builder =
<Year>1939</Year> <Year>1939</Year>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Single column as attribute" <| group_builder.specify "Single column as attribute" <|
t = data.table . take 4 t = data.table . take 4
r = t.to_xml [] ["Year"] r = t.to_xml [] ["Year"]
@ -89,7 +90,7 @@ add_specs suite_builder =
<Row Year="1951"/> <Row Year="1951"/>
<Row Year="1939"/> <Row Year="1939"/>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Single column as value" <| group_builder.specify "Single column as value" <|
t = data.table . take 4 t = data.table . take 4
r = t.to_xml [] [] "Year" r = t.to_xml [] [] "Year"
@ -100,7 +101,7 @@ add_specs suite_builder =
<Row>1951</Row> <Row>1951</Row>
<Row>1939</Row> <Row>1939</Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Different fields can be used as attributes, elements and value" <| group_builder.specify "Different fields can be used as attributes, elements and value" <|
t = data.table . take 1 t = data.table . take 1
r = t.to_xml ["Year"] ["Author", "Price"] "Title" r = t.to_xml ["Year"] ["Author", "Price"] "Title"
@ -111,7 +112,7 @@ add_specs suite_builder =
<Year>1859</Year> <Year>1859</Year>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Can use indexes to specify columns" <| group_builder.specify "Can use indexes to specify columns" <|
t = data.table . take 1 t = data.table . take 1
r = t.to_xml [3] [1, 2] 0 r = t.to_xml [3] [1, 2] 0
@ -122,7 +123,7 @@ add_specs suite_builder =
<Year>1859</Year> <Year>1859</Year>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Can use regex to specify columns for element and attribute" <| group_builder.specify "Can use regex to specify columns for element and attribute" <|
t = data.table . take 1 t = data.table . take 1
r = t.to_xml (Regex.compile ".*e") (Regex.compile ".*a.*") "Author" r = t.to_xml (Regex.compile ".*e") (Regex.compile ".*a.*") "Author"
@ -134,7 +135,7 @@ add_specs suite_builder =
<Price>9.99</Price> <Price>9.99</Price>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "The same fields can be used as attributes, elements and value" <| group_builder.specify "The same fields can be used as attributes, elements and value" <|
t = data.table . take 1 t = data.table . take 1
r = t.to_xml ["Author", "Price"] ["Author", "Price"] "Author" r = t.to_xml ["Author", "Price"] ["Author", "Price"] "Author"
@ -146,7 +147,7 @@ add_specs suite_builder =
<Price>9.99</Price> <Price>9.99</Price>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "If a field is specified duplicate times as an attribute or element it is only included once" <| group_builder.specify "If a field is specified duplicate times as an attribute or element it is only included once" <|
t = data.table . take 1 t = data.table . take 1
r = t.to_xml ["Author", "Price", "Author"] ["Author", "Price", "Price"] "Author" r = t.to_xml ["Author", "Price", "Author"] ["Author", "Price", "Price"] "Author"
@ -158,7 +159,7 @@ add_specs suite_builder =
<Price>9.99</Price> <Price>9.99</Price>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Root and Row tags can be set" <| group_builder.specify "Root and Row tags can be set" <|
t = data.table . take 1 t = data.table . take 1
r = t.to_xml ["Year"] ["Author", "Price"] "Title" "library" "book" r = t.to_xml ["Year"] ["Author", "Price"] "Title" "library" "book"
@ -169,7 +170,7 @@ add_specs suite_builder =
<Year>1859</Year> <Year>1859</Year>
</book> </book>
</library> </library>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Will warn if not all incoming columns specified" <| group_builder.specify "Will warn if not all incoming columns specified" <|
t = data.table . take 1 t = data.table . take 1
r = t.to_xml ["Year"] ["Author", "Price"] "Title" r = t.to_xml ["Year"] ["Author", "Price"] "Title"
@ -180,7 +181,7 @@ add_specs suite_builder =
<Year>1859</Year> <Year>1859</Year>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
Problems.expect_warning (Unexpected_Extra_Columns.Warning ["Last Borrowed"]) r Problems.expect_warning (Unexpected_Extra_Columns.Warning ["Last Borrowed"]) r
group_builder.specify "Will not warn if not all incoming columns specified, but warnings are ignored" <| group_builder.specify "Will not warn if not all incoming columns specified, but warnings are ignored" <|
t = data.table . take 1 t = data.table . take 1
@ -192,7 +193,7 @@ add_specs suite_builder =
<Year>1859</Year> <Year>1859</Year>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
Problems.assume_no_problems r Problems.assume_no_problems r
group_builder.specify "Will error if not all incoming columns specified and on_problems set to Report_Error" <| group_builder.specify "Will error if not all incoming columns specified and on_problems set to Report_Error" <|
t = data.table t = data.table
@ -210,23 +211,6 @@ add_specs suite_builder =
t = data.table t = data.table
r = t.to_xml ["Author", "Price"] ["Year"] "Not In Table" r = t.to_xml ["Author", "Price"] ["Year"] "Not In Table"
r.should_fail_with (No_Such_Column.Error "Not In Table") r.should_fail_with (No_Such_Column.Error "Not In Table")
group_builder.specify "XML should be pretty printed" <|
# pretty printed xml actually makes the tests less pretty
# so all the other tests depretty the xml before comparing
# this one makes sure it actually is pretty printed for users
t = data.table . take 2
r = t.to_xml ["Year"] ["Author", "Price"] "Title"
e = '<Table>\n'
+ ' <Row Author="Charles Dickens" Price="9.99">\n'
+ ' A Tale Of Two Cities\n'
+ ' <Year>1859</Year>\n'
+ ' </Row>\n'
+ ' <Row Author="F. Scott Fitzgerald" Price="5.99">\n'
+ ' The Great Gatsby\n'
+ ' <Year>1925</Year>\n'
+ ' </Row>\n'
+ '</Table>\n'
r . should_equal e
group_builder.specify "Illegal xml names are cleaned up in root_name and row_name" <| group_builder.specify "Illegal xml names are cleaned up in root_name and row_name" <|
t = data.table . take 1 t = data.table . take 1
r = t.to_xml ["Year"] ["Author", "Price"] "Title" "the library" "22book" r = t.to_xml ["Year"] ["Author", "Price"] "Title" "the library" "22book"
@ -237,7 +221,7 @@ add_specs suite_builder =
<Year>1859</Year> <Year>1859</Year>
</_22book> </_22book>
</the_library> </the_library>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Illegal xml names are cleaned up" <| group_builder.specify "Illegal xml names are cleaned up" <|
numeric_column_name = ["1", [10]] numeric_column_name = ["1", [10]]
illegal_column_name = ["Bad <chars> & symbols", [1]] illegal_column_name = ["Bad <chars> & symbols", [1]]
@ -255,7 +239,7 @@ add_specs suite_builder =
<Last_Borrowed>1999-01-02T03:40Z[UTC]</Last_Borrowed> <Last_Borrowed>1999-01-02T03:40Z[UTC]</Last_Borrowed>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Empty strings are empty attributes/elements. Nothing values omit the entire attribute/element" <| group_builder.specify "Empty strings are empty attributes/elements. Nothing values omit the entire attribute/element" <|
desc_column = ["desc", ["Col1 and Col2 both have values", "Col1 has value, Col2 Nothing", "Col1 empty string, Col2 has value", "Col1 and Col2 both blank string", "Col1 and Col2 both Nothing" ]] desc_column = ["desc", ["Col1 and Col2 both have values", "Col1 has value, Col2 Nothing", "Col1 empty string, Col2 has value", "Col1 and Col2 both blank string", "Col1 and Col2 both Nothing" ]]
col1 = ["Col1", ["Value1", "Value2", "", "", Nothing]] col1 = ["Col1", ["Value1", "Value2", "", "", Nothing]]
@ -290,7 +274,7 @@ add_specs suite_builder =
</Row> </Row>
<Row desc="Col1 and Col2 both Nothing"/> <Row desc="Col1 and Col2 both Nothing"/>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "Panic if wrong types passed in element_columns" <| group_builder.specify "Panic if wrong types passed in element_columns" <|
t = data.table t = data.table
r = Panic.recover Any (t.to_xml 1.23) r = Panic.recover Any (t.to_xml 1.23)
@ -342,7 +326,7 @@ add_specs suite_builder =
<unicode>👩‍🔬</unicode> <unicode>👩‍🔬</unicode>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
group_builder.specify "xml or special characters get escaped" <| group_builder.specify "xml or special characters get escaped" <|
xml_column = ["xml", ["</Table>", "<tag>12</tag>", '<r><c v="1"></c></r>']] xml_column = ["xml", ["</Table>", "<tag>12</tag>", '<r><c v="1"></c></r>']]
special_chars_column = ["special", ["<", "&>", "'"]] special_chars_column = ["special", ["<", "&>", "'"]]
@ -371,7 +355,7 @@ add_specs suite_builder =
<special>'</special> <special>'</special>
</Row> </Row>
</Table> </Table>
(depretty r).should_equal (depretty e) r.outer_xml.should_equal (depretty e)
main filter=Nothing = main filter=Nothing =
suite = Test.build suite_builder-> suite = Test.build suite_builder->