Skip to content

Instantly share code, notes, and snippets.

@TanvirHasan19
Created January 15, 2026 04:52
Show Gist options
  • Select an option

  • Save TanvirHasan19/51fa374e299b091399c137bfa2667e7c to your computer and use it in GitHub Desktop.

Select an option

Save TanvirHasan19/51fa374e299b091399c137bfa2667e7c to your computer and use it in GitHub Desktop.
Fix HTML entities in XML feeds
/**
* Fix HTML entities in XML feeds
*/
add_filter( 'adt_product_feed_xml_attribute_handling', function( $handled, $product, $key, $value, $feed_config, $channel_attributes, $feed ) {
if ( $handled || ! is_object( $product ) || ! is_object( $feed ) ) {
return $handled;
}
$target_feed_id = 37281;
$is_target_feed = false;
if ( method_exists( $feed, 'get_id' ) ) {
try {
$feed_id = (int) $feed->get_id();
$is_target_feed = ( $feed_id === $target_feed_id );
} catch ( \Exception $e ) {
// If get_id() fails, check by channel name instead
if ( isset( $feed_config['name'] ) && ( $feed_config['name'] === 'Skroutz' || $feed_config['name'] === 'Custom Feed' ) ) {
$is_target_feed = true;
}
}
} else {
// Fallback: check by channel name if get_id() method doesn't exist
if ( isset( $feed_config['name'] ) && ( $feed_config['name'] === 'Skroutz' || $feed_config['name'] === 'Custom Feed' ) ) {
$is_target_feed = true;
}
}
if ( ! $is_target_feed ) {
return $handled;
}
// Skip variations field (handled separately)
if ( 'skroutz_variations' === $key ) {
return $handled;
}
// Skip if field already exists in XML
if ( isset( $product->$key ) ) {
return $handled;
}
// Only process string values
if ( ! is_string( $value ) && ! is_numeric( $value ) ) {
return $handled;
}
// Convert to string
$decoded = (string) $value;
// Skip empty values
if ( '' === trim( $decoded ) ) {
return $handled;
}
try {
// Decode HTML entities (handles double/triple encoding)
$previous = '';
$iterations = 0;
$max_iterations = 10;
while ( $decoded !== $previous && $iterations < $max_iterations ) {
$previous = $decoded;
$decoded = html_entity_decode( $decoded, ENT_QUOTES | ENT_XML1 | ENT_HTML5, 'UTF-8' );
$iterations++;
}
// Validate UTF-8 and remove invalid XML characters
$decoded = wp_check_invalid_utf8( $decoded, true );
if ( class_exists( '\AdTribes\PFP\Helpers\Sanitization' ) ) {
$decoded = \AdTribes\PFP\Helpers\Sanitization::sanitize_utf8_for_xml( $decoded );
}
// Sanitize element name to prevent XML injection
$sanitized_key = preg_replace( '/[^a-zA-Z0-9_\-:]/', '', $key );
if ( '' === $sanitized_key ) {
$sanitized_key = 'value';
}
// Use DOMDocument to add the node with proper UTF-8 handling
// This ensures plain UTF-8 text without HTML entities
$dom = dom_import_simplexml( $product );
if ( $dom && $dom->ownerDocument ) {
try {
$child = $dom->ownerDocument->createElement( $sanitized_key );
if ( $child ) {
$text_node = $dom->ownerDocument->createTextNode( $decoded );
if ( $text_node ) {
$child->appendChild( $text_node );
$dom->appendChild( $child );
return true; // Successfully handled, skip default processing
}
}
} catch ( \DOMException $e ) {
// Log error but don't break feed generation
if ( function_exists( 'wc_get_logger' ) ) {
$logger = wc_get_logger();
$logger->warning(
'DOM operation failed in HTML entities fix: ' . $e->getMessage(),
array( 'source' => 'woo-product-feed-pro', 'key' => $key )
);
}
// Fall through to SimpleXML fallback
}
}
// Fallback to SimpleXML if DOM operations fail
// Note: This will still encode entities, but at least the feed won't break
try {
$fallback_value = htmlspecialchars( $decoded, ENT_XML1, 'UTF-8' );
$product->addChild( $sanitized_key, $fallback_value );
return true; // Handled, skip default processing
} catch ( \Exception $e ) {
// If even SimpleXML fails, log and let default handling proceed
if ( function_exists( 'wc_get_logger' ) ) {
$logger = wc_get_logger();
$logger->error(
'Failed to add XML element in HTML entities fix: ' . $e->getMessage(),
array( 'source' => 'woo-product-feed-pro', 'key' => $key )
);
}
// Return false to let default handling proceed
return $handled;
}
} catch ( \Exception $e ) {
// Catch any unexpected errors and log them
if ( function_exists( 'wc_get_logger' ) ) {
$logger = wc_get_logger();
$logger->error(
'Unexpected error in HTML entities fix: ' . $e->getMessage(),
array( 'source' => 'woo-product-feed-pro', 'key' => $key )
);
}
// Return false to let default handling proceed
return $handled;
}
}, 9, 7 );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment