diff --git a/src/utils/__tests__/xml.test.ts b/src/utils/__tests__/xml.test.ts
new file mode 100644
index 0000000000..aa71fa0901
--- /dev/null
+++ b/src/utils/__tests__/xml.test.ts
@@ -0,0 +1,151 @@
+import { parseXml } from "../xml"
+
+describe("parseXml", () => {
+ describe("type conversion", () => {
+ // Test the main change from the commit: no automatic type conversion
+ it("should not convert string numbers to numbers", () => {
+ const xml = `
+
+ 123
+ -456
+ 123.456
+
+ `
+
+ const result = parseXml(xml) as any
+
+ // Ensure these remain as strings and are not converted to numbers
+ expect(typeof result.root.numericString).toBe("string")
+ expect(result.root.numericString).toBe("123")
+
+ expect(typeof result.root.negativeNumericString).toBe("string")
+ expect(result.root.negativeNumericString).toBe("-456")
+
+ expect(typeof result.root.floatNumericString).toBe("string")
+ expect(result.root.floatNumericString).toBe("123.456")
+ })
+
+ it("should not convert string booleans to booleans", () => {
+ const xml = `
+
+ true
+ false
+
+ `
+
+ const result = parseXml(xml) as any
+
+ // Ensure these remain as strings and are not converted to booleans
+ expect(typeof result.root.boolTrue).toBe("string")
+ expect(result.root.boolTrue).toBe("true")
+
+ expect(typeof result.root.boolFalse).toBe("string")
+ expect(result.root.boolFalse).toBe("false")
+ })
+
+ it("should not convert attribute values to their respective types", () => {
+ const xml = `
+
+
+
+ `
+
+ const result = parseXml(xml) as any
+ const attributes = result.root.node
+
+ // Check that attributes remain as strings
+ expect(typeof attributes["@_id"]).toBe("string")
+ expect(attributes["@_id"]).toBe("123")
+
+ expect(typeof attributes["@_enabled"]).toBe("string")
+ expect(attributes["@_enabled"]).toBe("true")
+
+ expect(typeof attributes["@_disabled"]).toBe("string")
+ expect(attributes["@_disabled"]).toBe("false")
+
+ expect(typeof attributes["@_float"]).toBe("string")
+ expect(attributes["@_float"]).toBe("3.14")
+ })
+ })
+
+ describe("basic functionality", () => {
+ it("should correctly parse a simple XML string", () => {
+ const xml = `
+
+ Test Name
+ Some description
+
+ `
+
+ const result = parseXml(xml) as any
+
+ expect(result).toHaveProperty("root")
+ expect(result.root).toHaveProperty("name", "Test Name")
+ expect(result.root).toHaveProperty("description", "Some description")
+ })
+
+ it("should handle attributes correctly", () => {
+ const xml = `
+
+ - Item content
+
+ `
+
+ const result = parseXml(xml) as any
+
+ expect(result.root.item).toHaveProperty("@_id", "1")
+ expect(result.root.item).toHaveProperty("@_category", "test")
+ expect(result.root.item).toHaveProperty("#text", "Item content")
+ })
+
+ it("should support stopNodes parameter", () => {
+ const xml = `
+
+
+ - Should not parse this
+
+
+ `
+
+ const result = parseXml(xml, ["nestedXml"]) as any
+
+ // With stopNodes, the parser still parses the structure but stops at the specified node
+ expect(result.root.data.nestedXml).toBeTruthy()
+ expect(result.root.data.nestedXml).toHaveProperty("item", "Should not parse this")
+ })
+ })
+
+ describe("error handling", () => {
+ it("wraps parser errors with a descriptive message", () => {
+ // Use jest.spyOn to mock the XMLParser implementation
+ const mockParseFn = jest.fn().mockImplementation(() => {
+ throw new Error("Simulated parsing error")
+ })
+
+ const mockParserInstance = {
+ parse: mockParseFn,
+ }
+
+ // Spy on the XMLParser constructor to return our mock
+ const parserSpy = jest
+ .spyOn(require("fast-xml-parser"), "XMLParser")
+ .mockImplementation(() => mockParserInstance)
+
+ // Test that our function wraps the error appropriately
+ expect(() => parseXml("")).toThrow("Failed to parse XML: Simulated parsing error")
+
+ // Verify the parser was called with the expected options
+ expect(parserSpy).toHaveBeenCalledWith({
+ ignoreAttributes: false,
+ attributeNamePrefix: "@_",
+ parseAttributeValue: false,
+ parseTagValue: false,
+ trimValues: true,
+ stopNodes: [],
+ })
+
+ // Cleanup
+ parserSpy.mockRestore()
+ })
+ })
+})
diff --git a/src/utils/xml.ts b/src/utils/xml.ts
index 8ccd6e77ae..0fd6ef574c 100644
--- a/src/utils/xml.ts
+++ b/src/utils/xml.ts
@@ -10,13 +10,10 @@ export function parseXml(xmlString: string, stopNodes?: string[]): unknown {
const _stopNodes = stopNodes ?? []
try {
const parser = new XMLParser({
- // Preserve attribute types (don't convert numbers/booleans)
ignoreAttributes: false,
attributeNamePrefix: "@_",
- // Parse numbers and booleans in text nodes
- parseAttributeValue: true,
- parseTagValue: true,
- // Trim whitespace from text nodes
+ parseAttributeValue: false,
+ parseTagValue: false,
trimValues: true,
stopNodes: _stopNodes,
})