Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There is an exception appearing at XMLBuilder.build(obj): textValue.replace is not a function #600

Closed
5 of 6 tasks
HollisMeynell opened this issue Jul 30, 2023 · 4 comments
Labels
Pending Pending to be confirmed by user/author for some check/update/implementation

Comments

@HollisMeynell
Copy link

  • Are you running the latest version?
    yes ,now is 4.2.6
  • Have you included sample input, output, error, and expected output?
  • Have you checked if you are using correct configuration?
  • Did you try online tool?

Description

I want to modify an SVG in a Node environment. I have successfully serialized it into a JavaScript object, but when trying to convert it back to XML, I encountered errors that I cannot resolve.
I am providing the detailed output of the XML file and JSON.Perhaps I have misconfigured something, but I don't know how to set it up correctly, and I'm unsure of the proper configuration needed to preserve the attributes of the XML. As you can see, this is a piece of SVG code, and it may contain attributes with special characters, such as xlink:href.

Input

xml:

<svg xmlns="http://www.w3.org/2000/svg" width="618" height="1000" xmlns:xlink="http://www.w3.org/1999/xlink"
     viewBox="0 0 618 1000">
    <defs>
        <linearGradient id="color-text" gradientTransform="rotate(25)">
            <stop offset="5%" stop-color="#30cfd0"/>
            <stop offset="100%" stop-color="#330867"/>
        </linearGradient>
        <linearGradient id="h" gradientTransform="rotate(25)">
            <stop offset="5%" stop-color="#F2F2F2"/>
            <stop offset="65%" stop-color="#DBDBDB"/>
            <stop offset="100%" stop-color="#EAEAEA"/>
        </linearGradient>
        <linearGradient id="s" gradientTransform="rotate(25)">
            <stop offset="5%" stop-color="#FFA8A8"/>
            <stop offset="100%" stop-color="#FCFF00"/>
        </linearGradient>
        <linearGradient id="a" gradientTransform="rotate(25)">
            <stop offset="5%" stop-color="#FFA8A8"/>
            <stop offset="100%" stop-color="#FCFF00"/>
        </linearGradient>
        <linearGradient id="b" gradientTransform="rotate(25)">
            <stop offset="5%" stop-color="#FFA8A8"/>
            <stop offset="100%" stop-color="#FCFF00"/>
        </linearGradient>
        <linearGradient id="c" gradientTransform="rotate(25)">
            <stop offset="5%" stop-color="#FFA8A8"/>
            <stop offset="100%" stop-color="#FCFF00"/>
        </linearGradient>
        <linearGradient id="d" gradientTransform="rotate(25)">
            <stop offset="5%" stop-color="#FFA8A8"/>
            <stop offset="100%" stop-color="#FCFF00"/>
        </linearGradient>
        <linearGradient id="f" gradientTransform="rotate(25)">
            <stop offset="5%" stop-color="#FFA8A8"/>
            <stop offset="100%" stop-color="#FCFF00"/>
        </linearGradient>
        <pattern id="avatar" x="0" y="0" width="100%" height="100%">
            <image  width="300" height="300" preserveAspectRatio="xMidYMin slice"/>
        </pattern>
        <pattern id="bg" x="0" y="0" width="100%" height="100%">
            <image  width="618" height="1000" preserveAspectRatio="xMidYMin slice"/>
        </pattern>
    </defs>

    <rect width="100%" height="100%" fill="url(#bg)"/>
    <rect width="100%" height="100%" fill="#000" opacity="0.4"/>
    <rect x="30" y="30" width="300" height="300" fill="url(#avt)"/>
    <text id="text-info" x="0" y="480"
          font-family="JetBrainsMono Nerd Font"
          font-weight="900"
          font-size="100"

          stroke="#DDD"
          stroke-width="2"
          fill="url(#color-text)">
        <tspan x="0" dy="0" font-size="60">Stella-rium </tspan>
        <tspan mk="time" x="0" dy="100">05:32</tspan>
        <tspan mk="star" x="0" dy="100">6.17✫</tspan>
        <tspan mk="acc" x="0" dy="100">99.4%</tspan>
        <tspan mk="pp" x="0" dy="100">373.0</tspan>
        <tspan mk="combo" x="0" dy="100">2077X</tspan>
    </text>
    <text id="text-rank" x="430" y="230"
          font-family="JetBrains Mono ExtraBold"
          font-size="260"

          stroke="#FFF"
          stroke-width="5"
          fill="url(#s)" >
        <tspan id="rank-r">S</tspan>
        <tspan id="rank-l" x="360" opacity="0">S</tspan>
    </text>

    <svg id="mods" x="30" y="350" width="558" height="70" >
    </svg>

    <svg id="pp-show" x="603">
        <rect width="18" height="1000" fill="#FDFC47"/>
        <rect mk="pp-fc" width="18" height="900" fill="#B3315F"/>
        <rect mk="pp-now" width="18" height="600"  fill="#FA742B"/>
    </svg>
</svg>

Code

import {XMLParser, XMLBuilder} from "fast-xml-parser"

const opt = {
    preserveOrder: false,
    ignoreAttributes: false,
    parseTagValue: true,
    attributeNamePrefix: "$"
}
const parser = new XMLParser(opt);
const builder = new XMLBuilder(opt);

let templateStr = readTemplate('template/sp.svg');
const template = fs.readFileSync(path, 'utf8');
console.log(JSON.stringify(template));                                         // <---- json 1
/* some work */
console.log(JSON.stringify(template));                                         // <---- json 2
builder.build(template);                                                                  // <---- error

Output

json 1

{"svg":{"defs":{"linearGradient":[{"stop":[{"$offset":"5%","$stop-color":"#30cfd0"},{"$offset":"100%","$stop-color":"#330867"}],"$id":"color-text","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#F2F2F2"},{"$offset":"65%","$stop-color":"#DBDBDB"},{"$offset":"100%","$stop-color":"#EAEAEA"}],"$id":"h","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"s","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"a","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"b","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"c","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"d","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"f","$gradientTransform":"rotate(25)"}],"pattern":[{"image":{"$width":"300","$height":"300","$preserveAspectRatio":"xMidYMin slice"},"$id":"avatar","$x":"0","$y":"0","$width":"100%","$height":"100%"},{"image":{"$width":"618","$height":"1000","$preserveAspectRatio":"xMidYMin slice"},"$id":"bg","$x":"0","$y":"0","$width":"100%","$height":"100%"}]},"rect":[{"$width":"100%","$height":"100%","$fill":"url(#bg)"},{"$width":"100%","$height":"100%","$fill":"#000","$opacity":"0.4"},{"$x":"30","$y":"30","$width":"300","$height":"300","$fill":"url(#avt)"}],"text":[{"tspan":[{"#text":"Stella-rium","$x":"0","$dy":"0","$font-size":"60"},{"#text":"05:32","$mk":"time","$x":"0","$dy":"100"},{"#text":"6.17✫","$mk":"star","$x":"0","$dy":"100"},{"#text":"99.4%","$mk":"acc","$x":"0","$dy":"100"},{"#text":373,"$mk":"pp","$x":"0","$dy":"100"},{"#text":"2077X","$mk":"combo","$x":"0","$dy":"100"}],"$id":"text-info","$x":"0","$y":"480","$font-family":"JetBrainsMono Nerd Font","$font-weight":"900","$font-size":"100","$stroke":"#DDD","$stroke-width":"2","$fill":"url(#color-text)"},{"tspan":[{"#text":"S","$id":"rank-r"},{"#text":"S","$id":"rank-l","$x":"360","$opacity":"0"}],"$id":"text-rank","$x":"430","$y":"230","$font-family":"JetBrains Mono ExtraBold","$font-size":"260","$stroke":"#FFF","$stroke-width":"5","$fill":"url(#s)"}],"svg":[{"$id":"mods","$x":"30","$y":"350","$width":"558","$height":"70"},{"rect":[{"$width":"18","$height":"1000","$fill":"#FDFC47"},{"$mk":"pp-fc","$width":"18","$height":"900","$fill":"#B3315F"},{"$mk":"pp-now","$width":"18","$height":"600","$fill":"#FA742B"}],"$id":"pp-show","$x":"603"}],"$xmlns":"http://www.w3.org/2000/svg","$width":"618","$height":"1000","$xmlns:xlink":"http://www.w3.org/1999/xlink","$viewBox":"0 0 618 1000"}}

json 2

{"svg":{"defs":{"linearGradient":[{"stop":[{"$offset":"5%","$stop-color":"#30cfd0"},{"$offset":"100%","$stop-color":"#330867"}],"$id":"color-text","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#F2F2F2"},{"$offset":"65%","$stop-color":"#DBDBDB"},{"$offset":"100%","$stop-color":"#EAEAEA"}],"$id":"h","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"s","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"a","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"b","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"c","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"d","$gradientTransform":"rotate(25)"},{"stop":[{"$offset":"5%","$stop-color":"#FFA8A8"},{"$offset":"100%","$stop-color":"#FCFF00"}],"$id":"f","$gradientTransform":"rotate(25)"}],"pattern":[{"image":{"$width":"300","$height":"300","$preserveAspectRatio":"xMidYMin slice"},"$id":"avatar","$x":"0","$y":"0","$width":"100%","$height":"100%","$xlink:href":"https://a.ppy.sh/17064371"},{"image":{"$width":"618","$height":"1000","$preserveAspectRatio":"xMidYMin slice"},"$id":"bg","$x":"0","$y":"0","$width":"100%","$height":"100%","$xlink:href":"https://assets.ppy.sh/beatmaps/1456709/covers/list@2x.jpg"}]},"rect":[{"$width":"100%","$height":"100%","$fill":"url(#bg)"},{"$width":"100%","$height":"100%","$fill":"#000","$opacity":"0.4"},{"$x":"30","$y":"30","$width":"300","$height":"300","$fill":"url(#avt)"}],"text":[{"tspan":[{"#text":"Stella-rium","$x":"0","$dy":"0","$font-size":"60"},{"#text":"05:32","$mk":"time","$x":"0","$dy":"100"},{"#text":"6.00✫","$mk":"star","$x":"0","$dy":"100"},{"#text":"95.36%","$mk":"acc","$x":"0","$dy":"100"},{"#text":"346.1","$mk":"pp","$x":"0","$dy":"100"},{"#text":"5555X","$mk":"combo","$x":"0","$dy":"100"}],"$id":"text-info","$x":"0","$y":"480","$font-family":"JetBrainsMono Nerd Font","$font-weight":"900","$font-size":"100","$stroke":"#DDD","$stroke-width":"2","$fill":"url(#color-text)"},{"tspan":[{"#text":"S","$id":"rank-r"},{"#text":"S","$id":"rank-l","$x":"360","$opacity":"0"}],"$id":"text-rank","$x":"430","$y":"230","$font-family":"JetBrains Mono ExtraBold","$font-size":"260","$stroke":"#FFF","$stroke-width":"5","$fill":"url(#s)"}],"svg":[{"$id":"mods","$x":"30","$y":"350","$width":"558","$height":"70","svg":[{"g":{"path":[{"$id":"Vector","$fill-rule":"evenodd","$clip-rule":"evenodd","$d":"M87.1349 34.8514L74.4371 56.8506H25.5628L12.865 34.8514L25.5628 12.865H74.4371L87.1349 34.8514Z","$fill":"#66CCFF"},{"$id":"Vector_2","$fill-rule":"evenodd","$clip-rule":"evenodd","$d":"M25.5628 69.7157C25.1511 69.69 24.7523 69.69 24.3406 69.6514C23.5301 69.5742 22.7197 69.4198 21.9349 69.1882C20.7642 68.8409 19.632 68.3263 18.6028 67.6701C17.5736 67.014 16.6345 66.2035 15.8369 65.2772C15.1293 64.4539 15.0006 64.1966 14.4217 63.2832L1.7239 41.2839C1.22216 40.3191 1.06778 40.0875 0.707559 39.0583C0.308743 37.9004 0.0771719 36.6911 0.0128466 35.4689C-0.0514786 34.2468 0.0771719 33.0117 0.360203 31.8281C0.553179 31.0305 0.823344 30.2586 1.15784 29.5124C1.32508 29.1393 1.53092 28.792 1.7239 28.4189L14.4217 6.43252C15.0135 5.5191 15.1293 5.2618 15.8369 4.43844C16.6345 3.51216 17.5736 2.70166 18.6028 2.04554C19.632 1.38942 20.7642 0.874823 21.9349 0.527467C22.7197 0.295896 23.5173 0.141516 24.3406 0.0643252C24.7523 0.0257301 25.1511 0.0257301 25.5628 0H74.4371C75.5178 0.0514602 75.8008 0.0257301 76.8686 0.231571C78.0779 0.463142 79.2358 0.861958 80.3293 1.42802C81.4229 1.99408 82.4263 2.70166 83.314 3.55075C83.9058 4.11681 84.4461 4.73434 84.9093 5.40332C85.1409 5.73781 85.3467 6.08517 85.5654 6.43252L98.2632 28.4189C98.4562 28.7791 98.6492 29.1393 98.8293 29.5124C99.1638 30.2586 99.4339 31.0305 99.6269 31.8281C99.9099 33.0246 100.039 34.2468 99.9743 35.4689C99.9099 36.6911 99.6784 37.9133 99.2795 39.0583C98.9193 40.0875 98.7649 40.3191 98.2632 41.2839L85.5654 63.2703C84.9736 64.1837 84.8578 64.441 84.1502 65.2644C83.3526 66.1907 82.4135 67.0012 81.3843 67.6573C80.3551 68.3134 79.2229 68.828 78.0522 69.1754C77.2674 69.4069 76.4698 69.5613 75.6465 69.6385C75.2348 69.6771 74.836 69.6771 74.4243 69.7028C58.15 69.7157 41.85 69.7157 25.5628 69.7157Z","$fill":"#FFCC22"}],"g":{"path":[{"$id":"Vector_3","$d":"M80.2908 25.4343L56.9536 65.8563H64.261L83.9445 31.7639L80.2908 25.4343Z","$fill":"#555555"},{"$id":"Vector_4","$d":"M73.1636 13.0837L42.6863 65.8562H49.9936L76.8172 19.4005L73.1636 13.0837Z","$fill":"#555555"},{"$id":"Vector_5","$d":"M67.8374 3.85962H64.2224L30.2329 62.7172L32.034 65.8563H35.7263L69.6771 7.03729L67.8374 3.85962Z","$fill":"#555555"},{"$id":"Vector_6","$d":"M35.6748 3.85962L15.9656 38.0034L19.6064 44.3331L42.9822 3.85962H35.6748Z","$fill":"#555555"},{"$id":"Vector_7","$d":"M49.9421 3.85962L23.0928 50.3668L26.7464 56.6835L57.2494 3.85962H49.9421Z","$fill":"#555555"}],"$id":"Group"},"$id":"Frame","$clip-path":"url(#clip0_2432_184)"},"defs":{"clipPath":{"rect":{"$width":"100","$height":"69.7157","$fill":"white"},"$id":"clip0_2432_184"}},"$width":"100","$height":"70","$viewBox":"0 0 100 70","$fill":"none","$xmlns":"http://www.w3.org/2000/svg","$x":"0"}]},{"rect":[{"$width":"18","$height":"1000","$fill":"#FDFC47"},{"$mk":"pp-fc","$width":"18","$height":"900","$fill":"#B3315F"},{"$mk":"pp-now","$width":"18","$height":"600","$fill":"#FA742B"}],"$id":"pp-show","$x":"603"}],"$xmlns":"http://www.w3.org/2000/svg","$width":"618","$height":"1000","$xmlns:xlink":"http://www.w3.org/1999/xlink","$viewBox":"0 0 618 1000"}}

error

TypeError: textValue.replace is not a function
    at Builder.replaceEntitiesValue (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:241:29)
    at Builder.buildTextValNode (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:225:22)
    at Builder.j2x (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:101:23)
    at Builder.processTextOrObjNode (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:155:23)
    at Builder.j2x (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:120:32)
    at Builder.processTextOrObjNode (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:155:23)
    at Builder.j2x (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:120:32)
    at Builder.processTextOrObjNode (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:155:23)
    at Builder.j2x (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:139:21)
    at Builder.processTextOrObjNode (${root}/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js:155:23)

Node.js v20.4.0

expected data

I would like to obtain a correct and attribute-containing XML.

Would you like to work on this issue?

  • Yes
  • No

Bookmark this repository for further updates. Visit SoloThought to know about recent features.

@github-actions
Copy link

We're glad you find this project helpful. We'll try to address this issue ASAP. You can vist https://solothought.com to know recent features. Don't forget to star this repo.

@HollisMeynell
Copy link
Author

When encountering the issue, I noticed that the type of the textValue variable is function.

@amitguptagwl amitguptagwl added the Pending Pending to be confirmed by user/author for some check/update/implementation label Jul 30, 2023
@amitguptagwl
Copy link
Member

Hi @HollisMeynell

I tried to build from the json 2 and get no error.

const opt = {
    preserveOrder: false,
    ignoreAttributes: false,
    parseTagValue: true,
    attributeNamePrefix: "$"
}
const parser = new XMLParser(opt);
const builder = new XMLBuilder(opt);

// let template = fs.readFileSync( path.join(__dirname,'assets/sp.svg')).toString();
// const jsObj = parser.parse(template);  
const jsObj = require("./assets/sp_svg.json")                       // <---- json 2
builder.build(jsObj); 

@HollisMeynell
Copy link
Author

HollisMeynell commented Jul 31, 2023

Hi @HollisMeynell

I tried to build from the json 2 and get no error.

const opt = {
    preserveOrder: false,
    ignoreAttributes: false,
    parseTagValue: true,
    attributeNamePrefix: "$"
}
const parser = new XMLParser(opt);
const builder = new XMLBuilder(opt);

// let template = fs.readFileSync( path.join(__dirname,'assets/sp.svg')).toString();
// const jsObj = parser.parse(template);  
const jsObj = require("./assets/sp_svg.json")                       // <---- json 2
builder.build(jsObj); 

I've found the issue. Please try executing the following code anywhere before the builder.build(jsObj):

Object.prototype.setSvgText = function (str) {
    this["#text"] = str;
}

Modifying Object.prototype is not a good practice; it was my mistake in using it. I apologize for the inconvenience caused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Pending Pending to be confirmed by user/author for some check/update/implementation
Projects
None yet
Development

No branches or pull requests

2 participants