@@ -91,6 +91,8 @@ def __init__(self, valid_extensions=None):
9191 # function pointers
9292 self ._parser_map = {
9393 ".xml" : self .parse_xml_file ,
94+ # 20250527; add .lblx to be parsed as xml
95+ ".lblx" : self .parse_xml_file ,
9496 ".xls" : self .parse_xls_file ,
9597 ".xlsx" : self .parse_xls_file ,
9698 ".csv" : self .parse_csv_file ,
@@ -100,6 +102,25 @@ def __init__(self, valid_extensions=None):
100102 if not all ([extension in self ._parser_map for extension in self ._valid_extensions ]):
101103 raise ValueError ("One or more the provided extensions are not supported by the DOIInputUtil class." )
102104
105+ # 20250501: Detect UTF-16/UTF-8-BOM; decode
106+ def detect_and_decode_utf (Self , data : bytes ) -> str :
107+ # Detect and decode UTF-16 (with BOM)
108+ if data .startswith (b"\xff \xfe " ) or data .startswith (b"\xfe \xff " ):
109+ logger .info (f": Detected UTF-16 BOM." )
110+ return data .decode ("utf-16" )
111+
112+ try :
113+ # Try decoding as UTF-8 with BOM (utf-8-sig handles BOM automatically)
114+ logger .info (f": Trying to detect UTF-8 with BOM (utf-8-sig)." )
115+ decoded_data = data .decode ("utf-8-sig" )
116+ except UnicodeDecodeError :
117+ # Fallback
118+ logger .info (f":Could not decode as UTF-8-sig. Using fallback UTF-8 with replacement." )
119+ decoded_data = data .decode ("utf-8" , errors = "replace" )
120+
121+ dos_line_endings = decoded_data .replace ("\r \n " , "\n " ).replace ("\r " , "\n " ).replace ("\n " , "\r \n " )
122+ return dos_line_endings
123+
103124 def parse_xml_file (self , xml_path ):
104125 """
105126 Parses DOIs from a file with an .xml extension. The file is expected
@@ -473,12 +494,16 @@ def parse_json_file(self, json_path):
473494 validator = DOIServiceFactory .get_validator_service ()
474495
475496 # First read the contents of the file
476- with open (json_path , "r" ) as infile :
497+ # 20250501: read as binary to avoid encoding issues
498+ with open (json_path , "rb" ) as infile :
477499 # It's been observed that input files transferred from Windows-based
478500 # machines can append a UTF-8-BOM hex sequence, which breaks
479501 # JSON parsing later on. So we perform an encode-decode here to
480502 # ensure this sequence is stripped before continuing.
481- json_contents = infile .read ().encode ().decode ("utf-8-sig" )
503+ # 20250501: modify code to call routine to detect and decode UTF-16/UTF-8-BOM
504+ # json_contents = infile.read().encode().decode("utf-8-sig")
505+ json_contents = infile .read ()
506+ json_contents = self .detect_and_decode_utf (json_contents )
482507
483508 # Validate and parse the provide JSON label based on the service provider
484509 # configured within the INI. If there's a mismatch, the validation step
@@ -593,7 +618,7 @@ def _read_from_remote(self, input_url):
593618 raise InputFormatException (f"Could not read remote file { input_url } , reason: { str (http_err )} " )
594619
595620 with tempfile .NamedTemporaryFile (suffix = basename (parsed_url .path )) as temp_file :
596- temp_file .write (response .content )
621+ temp_file .write (response .content , encoding = "utf-8" )
597622 temp_file .seek (0 )
598623
599624 dois = self ._read_from_path (temp_file .name )
0 commit comments