Skip to content

Commit 0d578e3

Browse files
committed
Improve docs and get_attribute_names_with_prefix semantics for empty namespaces
1 parent f4654e0 commit 0d578e3

File tree

3 files changed

+219
-86
lines changed

3 files changed

+219
-86
lines changed

components/DataLiberation/EntityReader/WXREntityReader.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ private function read_next_entity() {
679679
$this->entity_opener_byte_offset = $this->xml->get_token_byte_offset_in_the_input_stream();
680680
}
681681

682-
$tag_with_namespace = $this->xml->get_tag_name_with_namespace();
682+
$tag_with_namespace = $this->xml->get_tag_namespace_and_local_name();
683683

684684
/**
685685
* Custom adjustment: the Accessibility WXR file uses a non-standard
@@ -762,7 +762,7 @@ private function read_next_entity() {
762762
$is_site_option_opener = (
763763
count( $this->xml->get_breadcrumbs() ) === 3 &&
764764
$this->xml->matches_breadcrumbs( array( 'rss', 'channel', '*' ) ) &&
765-
array_key_exists( $this->xml->get_tag_name_with_namespace(), $this->KNOWN_SITE_OPTIONS )
765+
array_key_exists( $this->xml->get_tag_namespace_and_local_name(), $this->KNOWN_SITE_OPTIONS )
766766
);
767767
if ( $is_site_option_opener ) {
768768
$this->entity_opener_byte_offset = $this->xml->get_token_byte_offset_in_the_input_stream();
@@ -870,13 +870,13 @@ private function read_next_entity() {
870870
* @return bool Whether a site_option entity was emitted.
871871
*/
872872
private function parse_site_option() {
873-
if ( ! array_key_exists( $this->xml->get_tag_name_with_namespace(), $this->KNOWN_SITE_OPTIONS ) ) {
873+
if ( ! array_key_exists( $this->xml->get_tag_namespace_and_local_name(), $this->KNOWN_SITE_OPTIONS ) ) {
874874
return false;
875875
}
876876

877877
$this->entity_type = 'site_option';
878878
$this->entity_data = array(
879-
'option_name' => $this->KNOWN_SITE_OPTIONS[ $this->xml->get_tag_name_with_namespace() ],
879+
'option_name' => $this->KNOWN_SITE_OPTIONS[ $this->xml->get_tag_namespace_and_local_name() ],
880880
'option_value' => $this->text_buffer,
881881
);
882882
$this->emit_entity();

components/XML/Tests/XMLProcessorTest.php

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,50 @@ public function test_get_attribute_names_with_prefix_returns_attribute_added_by_
410410
);
411411
}
412412

413+
public function test_get_attribute_names_with_prefix_with_namespace_and_local_name_prefix() {
414+
// XML with two attributes in the wp namespace and one in no namespace
415+
$xml = '<content xmlns:wp="http://wordpress.org/export/1.2/" wp:data-foo="bar" wp:data-bar="baz" data-foo="no-ns" />';
416+
$processor = XMLProcessor::create_from_string( $xml );
417+
$this->assertTrue( $processor->next_tag(), 'Querying a tag did not return true' );
418+
419+
// Should match only the wp:data-foo and wp:data-bar attributes
420+
$result = $processor->get_attribute_names_with_prefix( 'http://wordpress.org/export/1.2/', 'data-' );
421+
$this->assertSame(
422+
array(
423+
array( 'http://wordpress.org/export/1.2/', 'data-foo' ),
424+
array( 'http://wordpress.org/export/1.2/', 'data-bar' ),
425+
),
426+
$result,
427+
'get_attribute_names_with_prefix did not return the expected attributes for namespace and local name prefix'
428+
);
429+
430+
// Should match only the no-namespace data-foo attribute
431+
$result_no_ns = $processor->get_attribute_names_with_prefix( null, 'data-' );
432+
$this->assertSame(
433+
array(
434+
array( '', 'data-foo' ),
435+
),
436+
$result_no_ns,
437+
'get_attribute_names_with_prefix did not return the expected attributes for no namespace'
438+
);
439+
440+
// Should return empty array for a namespace that does not exist
441+
$result_none = $processor->get_attribute_names_with_prefix( 'http://notfound.org/', 'data-' );
442+
$this->assertSame(
443+
array(),
444+
$result_none,
445+
'get_attribute_names_with_prefix did not return empty array for non-existent namespace'
446+
);
447+
448+
// Should return empty array for a prefix that does not match
449+
$result_no_prefix = $processor->get_attribute_names_with_prefix( 'http://wordpress.org/export/1.2/', 'not-a-match-' );
450+
$this->assertSame(
451+
array(),
452+
$result_no_prefix,
453+
'get_attribute_names_with_prefix did not return empty array for non-matching prefix'
454+
);
455+
}
456+
413457
/**
414458
*
415459
* @covers XMLProcessor::__toString
@@ -1798,88 +1842,88 @@ public function test_doctype_in_tag_content_is_syntax_error() {
17981842
/**
17991843
*
18001844
* @covers XMLProcessor::set_attribute
1801-
* @covers XMLProcessor::get_namespace
1845+
* @covers XMLProcessor::get_tag_namespace
18021846
*/
18031847
public function test_setting_the_default_namespace_applies_to_element_and_children() {
18041848
$processor = XMLProcessor::create_from_string( '<root xmlns="http://example.com/ns1" attr="val1"><child attr="val2"><grandchild /></child></root>' );
18051849

18061850
// Root element should be in the http://example.com/ns1 namespace.
18071851
$this->assertTrue( $processor->next_tag( array( 'http://example.com/ns1', 'root' ) ) );
1808-
$this->assertEquals( 'http://example.com/ns1', $processor->get_namespace() );
1852+
$this->assertEquals( 'http://example.com/ns1', $processor->get_tag_namespace() );
18091853
// The attribute without a namespace prefix isn't namespaced.
18101854
$this->assertEquals( 'val1', $processor->get_attribute( '', 'attr' ), 'Unprefixed attribute attr was not found in the default namespace.' );
18111855

18121856
// Child element
18131857
$this->assertTrue( $processor->next_tag( array( 'http://example.com/ns1', 'child' ) ) );
1814-
$this->assertEquals( 'http://example.com/ns1', $processor->get_namespace() );
1858+
$this->assertEquals( 'http://example.com/ns1', $processor->get_tag_namespace() );
18151859
$this->assertEquals( 'val2', $processor->get_attribute( '', 'attr' ), 'Unprefixed attribute attr was not found in the default namespace.' );
18161860

18171861
// Grandchild element
18181862
$this->assertTrue( $processor->next_tag( array( 'http://example.com/ns1', 'grandchild' ) ) );
1819-
$this->assertEquals( 'http://example.com/ns1', $processor->get_namespace() );
1863+
$this->assertEquals( 'http://example.com/ns1', $processor->get_tag_namespace() );
18201864
}
18211865

18221866
/**
18231867
*
18241868
* @covers XMLProcessor::set_attribute
1825-
* @covers XMLProcessor::get_namespace
1869+
* @covers XMLProcessor::get_tag_namespace
18261870
*/
18271871
public function test_search_by_namespace() {
18281872
$processor = XMLProcessor::create_from_string( '<root xmlns="http://example.com/ns1" attr="val1"><child xmlns="http://example.com/ns2" attr="val2"><grandchild /></child></root>' );
18291873

18301874
// Root element should be in the http://example.com/ns1 namespace.
18311875
$this->assertTrue( $processor->next_tag( array( 'http://example.com/ns1', 'root' ) ) );
1832-
$this->assertEquals( 'http://example.com/ns1', $processor->get_namespace() );
1876+
$this->assertEquals( 'http://example.com/ns1', $processor->get_tag_namespace() );
18331877
// The attribute without a namespace prefix isn't namespaced.
18341878
$this->assertEquals( 'val1', $processor->get_attribute( '', 'attr' ), 'Unprefixed attribute attr was not found in the default namespace.' );
18351879

18361880
// Child element
18371881
$this->assertTrue( $processor->next_tag( array( 'http://example.com/ns2', 'child' ) ) );
1838-
$this->assertEquals( 'http://example.com/ns2', $processor->get_namespace() );
1882+
$this->assertEquals( 'http://example.com/ns2', $processor->get_tag_namespace() );
18391883
$this->assertEquals( 'val2', $processor->get_attribute( '', 'attr' ), 'Unprefixed attribute attr was not found in the default namespace.' );
18401884

18411885
// Grandchild element
18421886
$this->assertTrue( $processor->next_tag( array( 'http://example.com/ns2', 'grandchild' ) ) );
1843-
$this->assertEquals( 'http://example.com/ns2', $processor->get_namespace() );
1887+
$this->assertEquals( 'http://example.com/ns2', $processor->get_tag_namespace() );
18441888
}
18451889

18461890
/**
18471891
*
18481892
* @covers XMLProcessor::set_attribute
1849-
* @covers XMLProcessor::get_namespace
1893+
* @covers XMLProcessor::get_tag_namespace
18501894
*/
18511895
public function test_overriding_the_default_namespace_applies_to_element_and_children() {
18521896
$processor = XMLProcessor::create_from_string( '<root xmlns="http://example.com/ns1"><child xmlns="http://example.com/ns2" attr="val"><grandchild /></child></root>' );
18531897
$this->assertTrue( $processor->next_tag(['*', 'child']) );
18541898
$this->assertEquals( 'child', $processor->get_tag_local_name() );
1855-
$this->assertEquals( 'http://example.com/ns2', $processor->get_namespace() );
1899+
$this->assertEquals( 'http://example.com/ns2', $processor->get_tag_namespace() );
18561900
$this->assertEquals( 'val', $processor->get_attribute( '', 'attr' ), 'Unprefixed attribute attr was not found in the default namespace.' ); // Unprefixed attributes are in no namespace.
18571901

18581902
$processor->next_tag();
18591903
$this->assertEquals( 'grandchild', $processor->get_tag_local_name() );
1860-
$this->assertEquals( 'http://example.com/ns2', $processor->get_namespace() );
1904+
$this->assertEquals( 'http://example.com/ns2', $processor->get_tag_namespace() );
18611905
}
18621906

18631907
/**
18641908
*
18651909
* @covers XMLProcessor::set_attribute
1866-
* @covers XMLProcessor::get_namespace
1910+
* @covers XMLProcessor::get_tag_namespace
18671911
*/
18681912
public function test_changing_default_namespace_to_empty_string_removes_namespace() {
18691913
$processor = XMLProcessor::create_from_string( '<root xmlns="http://example.com/ns1"><child xmlns="" attr="val"><grandchild /></child></root>' );
18701914

18711915
// Root element
18721916
$this->assertTrue( $processor->next_tag() );
1873-
$this->assertEquals( 'http://example.com/ns1', $processor->get_namespace() );
1917+
$this->assertEquals( 'http://example.com/ns1', $processor->get_tag_namespace() );
18741918

18751919
// Child element - default namespace removed
18761920
$this->assertTrue( $processor->next_tag() );
1877-
$this->assertEquals( '', $processor->get_namespace() ); // Empty string indicates no namespace.
1921+
$this->assertEquals( '', $processor->get_tag_namespace() ); // Empty string indicates no namespace.
18781922
$this->assertEquals( 'val', $processor->get_attribute( '', 'attr' ) ); // Unprefixed attributes are in no namespace.
18791923

18801924
// Grandchild element - inherits no namespace from parent
18811925
$this->assertTrue( $processor->next_tag() );
1882-
$this->assertEquals( '', $processor->get_namespace() ); // Empty string indicates no namespace.
1926+
$this->assertEquals( '', $processor->get_tag_namespace() ); // Empty string indicates no namespace.
18831927
}
18841928

18851929
/**
@@ -1912,7 +1956,7 @@ public function test_rejects_duplicate_unprefixed_attributes_on_element_with_def
19121956
*
19131957
* @covers XMLProcessor::pause
19141958
* @covers XMLProcessor::resume
1915-
* @covers XMLProcessor::get_namespace
1959+
* @covers XMLProcessor::get_tag_namespace
19161960
* @covers XMLProcessor::get_breadcrumbs
19171961
*/
19181962
public function test_pause_and_resume_with_complex_namespaces_and_nesting() {
@@ -2108,7 +2152,7 @@ public function test_pause_and_resume_with_complex_namespaces_and_nesting() {
21082152
$this->assertTrue( $processor->next_tag() ); // admin:highlight
21092153

21102154
$this->assertEquals( 'highlight', $processor->get_tag_local_name() );
2111-
$this->assertEquals( 'http://admin.example.com', $processor->get_namespace() );
2155+
$this->assertEquals( 'http://admin.example.com', $processor->get_tag_namespace() );
21122156
$this->assertEquals( 'yellow', $processor->get_attribute( '', 'color' ) );
21132157

21142158
// TEST 1: Pause and resume 5 times at the same spot (admin:highlight)
@@ -2123,7 +2167,7 @@ public function test_pause_and_resume_with_complex_namespaces_and_nesting() {
21232167

21242168
$this->assertTrue( $resumed->next_tag(), "Iteration $i: Failed to find tag after resume" );
21252169
$this->assertEquals( 'highlight', $resumed->get_tag_local_name(), "Iteration $i: Wrong tag name" );
2126-
$this->assertEquals( 'http://admin.example.com', $resumed->get_namespace(), "Iteration $i: Wrong namespace" );
2170+
$this->assertEquals( 'http://admin.example.com', $resumed->get_tag_namespace(), "Iteration $i: Wrong namespace" );
21272171
$this->assertEquals( 'yellow', $resumed->get_attribute( '', 'color' ), "Iteration $i: Wrong attribute value" );
21282172

21292173
// Verify we can get the text content
@@ -2147,7 +2191,7 @@ public function test_pause_and_resume_with_complex_namespaces_and_nesting() {
21472191

21482192
$this->assertTrue( $resumed->next_tag() );
21492193
$this->assertEquals( 'emphasis', $resumed->get_tag_local_name() );
2150-
$this->assertEquals( 'http://meta.example.com', $resumed->get_namespace() );
2194+
$this->assertEquals( 'http://meta.example.com', $resumed->get_tag_namespace() );
21512195
$this->assertTrue( $resumed->next_token() );
21522196
$this->assertEquals( 'emphasized text', $resumed->get_modifiable_text() );
21532197

@@ -2168,7 +2212,7 @@ public function test_pause_and_resume_with_complex_namespaces_and_nesting() {
21682212

21692213
$this->assertTrue( $resumed->next_tag() );
21702214
$this->assertEquals( 'code-line', $resumed->get_tag_local_name() );
2171-
$this->assertEquals( 'http://content.example.com', $resumed->get_namespace() );
2215+
$this->assertEquals( 'http://content.example.com', $resumed->get_tag_namespace() );
21722216
$this->assertEquals( '1', $resumed->get_attribute( '', 'number' ) );
21732217
$this->assertTrue( $resumed->next_token() );
21742218
$this->assertEquals( 'function example_function() {', $resumed->get_modifiable_text() );
@@ -2186,7 +2230,7 @@ public function test_pause_and_resume_with_complex_namespaces_and_nesting() {
21862230

21872231
$this->assertTrue( $resumed->next_tag() );
21882232
$this->assertEquals( 'icon', $resumed->get_tag_local_name() );
2189-
$this->assertEquals( 'http://admin.example.com', $resumed->get_namespace() );
2233+
$this->assertEquals( 'http://admin.example.com', $resumed->get_tag_namespace() );
21902234
$this->assertTrue( $resumed->next_token() );
21912235
$this->assertEquals( '⚠️', $resumed->get_modifiable_text() );
21922236

@@ -2205,7 +2249,7 @@ public function test_pause_and_resume_with_complex_namespaces_and_nesting() {
22052249

22062250
$this->assertTrue( $resumed->next_tag() );
22072251
$this->assertEquals( 'engagement-metrics', $resumed->get_tag_local_name() );
2208-
$this->assertEquals( 'http://meta.example.com', $resumed->get_namespace() );
2252+
$this->assertEquals( 'http://meta.example.com', $resumed->get_tag_namespace() );
22092253
$this->assertEquals( '1500', $resumed->get_attribute( '', 'views' ) );
22102254
$this->assertEquals( '25', $resumed->get_attribute( '', 'likes' ) );
22112255
$this->assertEquals( '8', $resumed->get_attribute( '', 'shares' ) );
@@ -2262,7 +2306,7 @@ public function test_pause_and_resume_with_complex_namespaces_and_nesting() {
22622306

22632307
$this->assertTrue( $resumed->next_tag() );
22642308
$this->assertEquals( 'name', $resumed->get_tag_local_name() );
2265-
$this->assertEquals( 'http://content.example.com', $resumed->get_namespace() );
2309+
$this->assertEquals( 'http://content.example.com', $resumed->get_tag_namespace() );
22662310
$this->assertTrue( $resumed->next_token() );
22672311
$this->assertEquals( 'Alice Johnson', $resumed->get_modifiable_text() );
22682312

@@ -2326,7 +2370,7 @@ public function test_streaming_pause_resume_with_real_wxr_data() {
23262370
$found = false;
23272371
while ( $processor->next_tag() ) {
23282372
if ( $processor->get_tag_local_name() === $position['element'] &&
2329-
$processor->get_namespace() === $position['namespace'] ) {
2373+
$processor->get_tag_namespace() === $position['namespace'] ) {
23302374
$found = true;
23312375
break;
23322376
}
@@ -2336,7 +2380,7 @@ public function test_streaming_pause_resume_with_real_wxr_data() {
23362380

23372381
// Verify we're at the expected element
23382382
$this->assertEquals( $position['element'], $processor->get_tag_local_name(), "Wrong element at position {$i}" );
2339-
$this->assertEquals( $position['namespace'], $processor->get_namespace(), "Wrong namespace at position {$i}" );
2383+
$this->assertEquals( $position['namespace'], $processor->get_tag_namespace(), "Wrong namespace at position {$i}" );
23402384

23412385
// Test element-specific properties
23422386
if ( isset( $position['has_version_attr'] ) && $position['has_version_attr'] ) {
@@ -2356,7 +2400,7 @@ public function test_streaming_pause_resume_with_real_wxr_data() {
23562400
// The resumed processor should find the same element when next_tag() is called
23572401
$this->assertTrue( $resumed->next_tag(), "Failed to resume at position {$i}" );
23582402
$this->assertEquals( $position['element'], $resumed->get_tag_local_name(), "Wrong element after resume at position {$i}" );
2359-
$this->assertEquals( $position['namespace'], $resumed->get_namespace(), "Wrong namespace after resume at position {$i}" );
2403+
$this->assertEquals( $position['namespace'], $resumed->get_tag_namespace(), "Wrong namespace after resume at position {$i}" );
23602404

23612405
// Verify element properties are preserved after resume
23622406
if ( isset( $position['has_version_attr'] ) && $position['has_version_attr'] ) {
@@ -2404,7 +2448,7 @@ public function test_streaming_pause_resume_with_real_wxr_data() {
24042448
// Verify we can resume at the same item element
24052449
$this->assertTrue( $resumed->next_tag(), "Stress cycle {$cycle}: Failed to resume" );
24062450
$this->assertEquals( 'item', $resumed->get_tag_local_name(), "Stress cycle {$cycle}: Wrong element" );
2407-
$this->assertEquals( '', $resumed->get_namespace(), "Stress cycle {$cycle}: Wrong namespace" );
2451+
$this->assertEquals( '', $resumed->get_tag_namespace(), "Stress cycle {$cycle}: Wrong namespace" );
24082452

24092453
// Verify we can navigate to child elements after resume
24102454
$this->assertTrue( $resumed->next_tag( 'title' ), "Stress cycle {$cycle}: Failed to find title child" );

0 commit comments

Comments
 (0)