XML Name Cannot Begin with the '%' character

◇◆丶佛笑我妖孽 提交于 2021-01-26 20:30:49

问题


I'm trying to post XML to a web service using jQuery. I'm getting a response back that I didn't expect:

"Name Cannot begin with the '%' character, hexadecimal value 0x25. Line 1, position 65."

Code

$(function() {
    var xmlStr = '<?xml version="1.0" encoding="utf-8" ?><TransactionSetup xmlns="obsfucated"><Credentials><AccountID>1043155</AccountID><AccountToken>obsfucated</AccountToken><AcceptorID>obsfucated</AcceptorID></Credentials><Application><ApplicationID>obsfucated</ApplicationID><ApplicationVersion>1.0</ApplicationVersion><ApplicationName>Test</ApplicationName></Application><Terminal><TerminalID>01</TerminalID><CardholderPresentCode>2</CardholderPresentCode><CardInputCode>5</CardInputCode><TerminalCapabilityCode>3</TerminalCapabilityCode><TerminalEnvironmentCode>2</TerminalEnvironmentCode><CardPresentCode>2</CardPresentCode><MotoECICode>1</MotoECICode><CVVPresenceCode>1</CVVPresenceCode></Terminal><Transaction><TransactionAmount>SPI_CartTotalFinal</TransactionAmount></Transaction><TransactionSetup><TransactionSetupMethod>1</TransactionSetupMethod><Embedded>1</Embedded><AutoReturn>1</AutoReturn><ReturnURL>Obsfucated</ReturnURL><CustomCss>body{margin-left:50px;font-family:arial;font-size:large;border:none;}</CustomCss></TransactionSetup></TransactionSetup>',
        guid;
    $.ajax({
        type: 'POST',
        url: 'webserviceurl',
        contentType: "text/xml",
        dataType: "xml",
        data: {
            Action: $('#Action').val(),
            IsAjax: $('#IsAjax').val(),
            xml: xmlStr,
        },
        success: function(response) {
            guid = response;
            console.log('success' + guid);
        },
        error: function (jqXHR, tranStatus, errorThrown) {
        console.log(
            'Status: ' + jqXHR.status + ' ' + jqXHR.statusText + '. ' +
            'Response: ' + jqXHR.responseText
        );
    }
    });

UPDATE - Posted Data

<TransactionSetup xmlns="https://www.obsfucated.com"%3E%20%3CCredentials%3E%20%3CAccountID%3E1223135%3C/AccountID%3E%20%3CAccountToken%3EA9A22221CBE222ED0E287D6F34B0222E0F928E4DDF6C37B945CE05F78054DF95966FC201%3C/AccountToken%3E%20%3CAcceptorID%322228907%3C/AcceptorID%3E%20%3C/Credentials%3E%20%3CApplication%3E%20%3CApplicationID%3E8003%3C/ApplicationID%3E%20%3CApplicationVersion%3E1.0%3C/ApplicationVersion%3E%20%3CApplicationName%3EHostedPayments.CSharp%3C/ApplicationName%3E%20%3C/Application%3E%20%3CTerminal%3E%20%3CTerminalID%3E01%3C/TerminalID%3E%20%3CCardholderPresentCode%3E2%3C/CardholderPresentCode%3E%20%3CCardInputCode%3E5%3C/CardInputCode%3E%20%3CTerminalCapabilityCode%3E3%3C/TerminalCapabilityCode%3E%20%3CTerminalEnvironmentCode%3E2%3C/TerminalEnvironmentCode%3E%20%3CCardPresentCode%3E2%3C/CardPresentCode%3E%20%3CMotoECICode%3E1%3C/MotoECICode%3E%20%3CCVVPresenceCode%3E1%3C/CVVPresenceCode%3E%20%3C/Terminal%3E%20%3CTransaction%3E%20%3CTransactionAmount%3E0.20%3C/TransactionAmount%3E%20%3C/Transaction%3E%20%3CTransactionSetup%3E%20%3CTransactionSetupMethod%3E1%3C/TransactionSetupMethod%3E%20%3CEmbedded%3E1%3C/Embedded%3E%20%3CAutoReturn%3E1%3C/AutoReturn%3E%20%3CReturnURL%3Ehttp://shop.masterssupply.net/webcattest/WebCatPageServer.exe%3C/ReturnURL%3E%20%3CCustomCss%3E%20.tdHeader%20{%20%20%20%20%20background-color:%20%23F8F8F8;%20%20%20%20%20padding:%205px;%20%20%20%20%20font-weight:%20bold;%20}%20.tdLabel%20{%20%20%20%20%20font-weight:%20bold;%20%20%20%20%20text-align:%20right;%20%20%20%20%20padding-right:%2010px;%20%20%20%20%20padding-left:%2010px;%20%20%20%20%20padding-top:%2010px;%20%20%20%20%20padding-bottom:%2010px;%20}%20.tdField%20{%20%20%20%20%20padding-right:%2010px;%20%20%20%20%20padding-left:%2010px;%20%20%20%20%20padding-top:%2010px;%20%20%20%20%20padding-bottom:%2010px;%20}%20.content%20{%20%20%20%20%20padding-left:%2010px;%20%20%20%20%20padding-top:%205px;%20%20%20%20%20padding-bottom:%205px;%20%20%20%20%20border-left-style:%20none;%20%20%20%20%20border-left-width:%20none;%20%20%20%20%20border-left-color:%20none;%20%20%20%20%20border-right-style:%20none;%20%20%20%20%20border-right-width:%20none;%20%20%20%20%20border-right-color:%20none;%20}%20.tdTransactionButtons%20{%20%20%20%20%20text-align:%20left;%20%20%20%20%20padding-top:%205px;%20%20%20%20%20height:%2035px;%20%20%20%20%20border-top-style:%20none;%20%20%20%20%20border-top-width:%20none;%20%20%20%20%20border-top-color:%20none;%20%20%20%20%20vertical-align:%20middle;%20}%20body%20{%20%20%20%20%20margin-left:%20none;%20%20%20%20%20font-family:%20arial;%20%20%20%20%20font-size:%2012px;%20%20%20%20%20border:%20none;%20}%20.buttonEmbedded:link%20{%20%20%20%20%20font-size:%2013px;%20%20%20%20%20font-weight:%20bold;%20%20%20%20%20padding-right:%2010px;%20%20%20%20%20padding-left:%2010px;%20%20%20%20%20padding-top:%204px;%20%20%20%20%20padding-bottom:%204px;%20%20%20%20%20border:%204px%20solid%20%23ce701a;%20%20%20%20%20color:%20%23ffffff;%20%20%20%20%20background-color:%20%23ce701a;%20%20%20%20%20text-decoration:%20none;%20%20%20%20%20border-top-style:%20solid;%20%20%20%20%20border-top-width:%201px;%20%20%20%20%20border-top-color:%20%23ce701a;%20%20%20%20%20border-right-color:%20%23ce701a;%20%20%20%20%20border-left-color:%20%23ce701a;%20%20%20%20%20border-bottom-color:%20%23ce701a;%20}%20.buttonCancel{%20%20%20%20%20border:%201px%20solid%20%23444;%20%20%20%20%20font-weight:%20bold;%20%20%20%20%20color:%20%23fff;%20%20%20%20%20border:%201px%20solid%20%23444;%20%20%20%20%20background-color:%20%237c7c7c;%20%20%20%20%20box-shadow:%20none;%20%20%20%20%20border-radius:%200px;%20%20%20%20%20padding:%206px%2012px;%20%20%20%20%20font-size:%2014px;%20%20%20%20%20line-height:%204.428571;%20%20%20%20%20text-decoration:%20none;%20%20%20%20%20padding-right:%2010px;%20%20%20%20%20padding-left:%2010px;%20%20%20%20%20padding-top:%204px;%20%20%20%20%20padding-bottom:%204px;%20%20%20%20%20border-top-style:%20solid;%20%20%20%20%20border-top-width:%201px;%20%20%20%20%20border-top-color:%20%23838383;%20%20%20%20%20border-right-color:%20%23838383;%20%20%20%20%20border-left-color:%20%23838383;%20%20%20%20%20border-bottom-color:%20%23838383;%20}%20.buttonCancel:link%20{%20%20%20%20%20color:%20%23fff;%20}%20.buttonCancel:visited%20{%20%20%20%20%20color:%20%23fff;%20}%20%3C/CustomCss%3E%20%3C/TransactionSetup%3E%20%3C/TransactionSetup%3E%20

As you can see the data is url encoded. I assume that's where the issue is, but I don't know how to fix it. Any guidance would be helpful. Thanks!


回答1:


The error is produced due to the space right before the ending ? sign as seen below

<?xml version="1.0" encoding="utf-8" ?>

You can check your xml string and return it a bit more tidy with the way provided in the snippet.

var xmlString ='<?xml version=\"1.0\" encoding=\"utf-8\" ?><TransactionSetup xmlns=\"obsfucated\"><Credentials><AccountID>1043155</AccountID><AccountToken>obsfucated</AccountToken><AcceptorID>obsfucated</AcceptorID></Credentials><Application><ApplicationID>obsfucated</ApplicationID><ApplicationVersion>1.0</ApplicationVersion><ApplicationName>Test</ApplicationName></Application><Terminal><TerminalID>01</TerminalID><CardholderPresentCode>2</CardholderPresentCode><CardInputCode>5</CardInputCode><TerminalCapabilityCode>3</TerminalCapabilityCode><TerminalEnvironmentCode>2</TerminalEnvironmentCode><CardPresentCode>2</CardPresentCode><MotoECICode>1</MotoECICode><CVVPresenceCode>1</CVVPresenceCode></Terminal><Transaction><TransactionAmount>SPI_CartTotalFinal</TransactionAmount></Transaction><TransactionSetup><TransactionSetupMethod>1</TransactionSetupMethod><Embedded>1</Embedded><AutoReturn>1</AutoReturn><ReturnURL>Obsfucated</ReturnURL><CustomCss>body{margin-left:50px;font-family:arial;font-size:large;border:none;}</CustomCss></TransactionSetup></TransactionSetup>';
var xmlDoc = $.parseXML( xmlString );
var newxmlString = (new XMLSerializer()).serializeToString(xmlDoc);
console.log([xmlString,newxmlString]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Difference in XML strings before and after

EDIT

After a closer look at the code posted and after fixing the missing }) part i would say your problem is the contentType that is declared wrongly.

To explain better you should declare contentType as text/plain because i think it falls back to default application/x-www-form-urlencoded. Have a look at contentType in jquery ajax documentation it is specified that

Note: For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server.

In addition:

Have a look at HTTP access control (CORS) about content-Type and also check this answer in SO.

Initial Code

$(function() {
    var xmlStr = '<?xml version="1.0" encoding="utf-8" ?><TransactionSetup xmlns="obsfucated"><Credentials><AccountID>1043155</AccountID><AccountToken>obsfucated</AccountToken><AcceptorID>obsfucated</AcceptorID></Credentials><Application><ApplicationID>obsfucated</ApplicationID><ApplicationVersion>1.0</ApplicationVersion><ApplicationName>Test</ApplicationName></Application><Terminal><TerminalID>01</TerminalID><CardholderPresentCode>2</CardholderPresentCode><CardInputCode>5</CardInputCode><TerminalCapabilityCode>3</TerminalCapabilityCode><TerminalEnvironmentCode>2</TerminalEnvironmentCode><CardPresentCode>2</CardPresentCode><MotoECICode>1</MotoECICode><CVVPresenceCode>1</CVVPresenceCode></Terminal><Transaction><TransactionAmount>SPI_CartTotalFinal</TransactionAmount></Transaction><TransactionSetup><TransactionSetupMethod>1</TransactionSetupMethod><Embedded>1</Embedded><AutoReturn>1</AutoReturn><ReturnURL>Obsfucated</ReturnURL><CustomCss>body{margin-left:50px;font-family:arial;font-size:large;border:none;}</CustomCss></TransactionSetup></TransactionSetup>',
        guid;
    $.ajax({
        type: 'POST',
        url: 'webserviceurl',
        contentType: "text/xml",
        dataType: "xml",
        data: {
            Action: $('#Action').val(),
            IsAjax: $('#IsAjax').val(),
            xml: xmlStr,
        },
        success: function(response) {
            guid = response;
            console.log('success' + guid);
        },
        error: function (jqXHR, tranStatus, errorThrown) {
        console.log('Status: ' + jqXHR.status + ' '+jqXHR.statusText+'. '+'Response: '+jqXHR.responseText);
        }
    });
});

Proposed Code

$(function() {
var xmlStr = '<?xml version=\"1.0\" encoding=\"utf-8\"?><TransactionSetup xmlns=\"obsfucated\"><Credentials><AccountID>1043155</AccountID><AccountToken>obsfucated</AccountToken><AcceptorID>obsfucated</AcceptorID></Credentials><Application><ApplicationID>obsfucated</ApplicationID><ApplicationVersion>1.0</ApplicationVersion><ApplicationName>Test</ApplicationName></Application><Terminal><TerminalID>01</TerminalID><CardholderPresentCode>2</CardholderPresentCode><CardInputCode>5</CardInputCode><TerminalCapabilityCode>3</TerminalCapabilityCode><TerminalEnvironmentCode>2</TerminalEnvironmentCode><CardPresentCode>2</CardPresentCode><MotoECICode>1</MotoECICode><CVVPresenceCode>1</CVVPresenceCode></Terminal><Transaction><TransactionAmount>SPI_CartTotalFinal</TransactionAmount></Transaction><TransactionSetup><TransactionSetupMethod>1</TransactionSetupMethod><Embedded>1</Embedded><AutoReturn>1</AutoReturn><ReturnURL>Obsfucated</ReturnURL><CustomCss>body{margin-left:50px;font-family:arial;font-size:large;border:none;}</CustomCss></TransactionSetup></TransactionSetup>',
guid;       
var jqxhr = $.ajax({
        type: "POST",
        url: "webserviceurl",
        contentType: "text/plain",
        dataType: "xml",
        data: {
            Action: $('#Action').val(),
            IsAjax: $('#IsAjax').val(),
            xml: xmlStr,
        }
})
.done(function(data) {
    guid = data;
    console.log(data.responseXML);      
})
.fail(function( jqXHR, textStatus,errorThrown ) {
    console.log("Request failed: "+errorThrown+" - "+textStatus);
}); 
});



回答2:


I took a look at the code and found a few issues to look into.

  1. The function code you posted is missing a closing '});' to close out the function and ajax call appropriately. This may just be due to a copy-paste problem when you posted your question. But, to be clear. The following blocks of code will need to be there for it to work.

    $(function() {
        var xmlStr = 'validxml', guid;
    
        $.ajax({
            option1:"option1"
        });
    //basically, this last closing bracket/paren was missing in the sample code
    });
    
  2. The XML you are posting doesn't seem to be valid. There is an opening <TransactionSetup> tag but there seem to be TWO closing </TransactionSetup> tags at the end. Most likely this won't cause issues with how jQuery posts the data, but it will probably cause issues server-side when it's time to deserialize the XML.

  3. The data you are showing as posted is curious for a couple reasons. First, it doesn't include the XML prolog at the beginning of your javascript variable shows. (Instead, it just starts with <TransactionSetup>. Second, the encoding is odd since it appears that things after the xmlns attribute are getting encoded but nothing before that. I think the source of your problem based on the error message is that the server is having a really hard time parsing the XML because it's not encoded at the beginning and then suddenly becomes encoded part way through. This makes sense based on the error message "Name Cannot begin with the '%' character" because it's encountering the encoded angle brackets in your XML when it doesn't expect to.

My recommendation would be to:

  1. Verify all your closing brackets/parenthesis are correct
  2. Verify the XML is all valid (proper opening and matching closing tags)
  3. Then start troubleshooting your issue if it still exists. The first thing I'd suggest changing would be to remove the contentType: "text/xml" option entirely from the ajax() call since that's not normally something you need to set or change when posting XML in my experience. My guess is if you remove that option you'll be closer to identifying the issue. If removing it doesn't help, try changing it to contentType: "application/xml".



回答3:


Have you tried sending an XML document instead of a string?

    data: {
        Action: $('#Action').val(),
        IsAjax: $('#IsAjax').val(),
        xml: $.parseXML(xmlStr),
    }



回答4:


The data that be posted is not actually a xml, it is an object which have a xml property. So the setting contentType: "text/xml" is not suitable for your ajax request.

By default, data passed in to the data as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". To prevent data be sent in url encoded format, you could consider to convert your posted data to a json string and change the setting contentType to "application/json; charset=utf-8".

$(function() {
    var xmlStr = '<?xml version="1.0" encoding="utf-8" ?><TransactionSetup xmlns="obsfucated"><Credentials><AccountID>1043155</AccountID><AccountToken>obsfucated</AccountToken><AcceptorID>obsfucated</AcceptorID></Credentials><Application><ApplicationID>obsfucated</ApplicationID><ApplicationVersion>1.0</ApplicationVersion><ApplicationName>Test</ApplicationName></Application><Terminal><TerminalID>01</TerminalID><CardholderPresentCode>2</CardholderPresentCode><CardInputCode>5</CardInputCode><TerminalCapabilityCode>3</TerminalCapabilityCode><TerminalEnvironmentCode>2</TerminalEnvironmentCode><CardPresentCode>2</CardPresentCode><MotoECICode>1</MotoECICode><CVVPresenceCode>1</CVVPresenceCode></Terminal><Transaction><TransactionAmount>SPI_CartTotalFinal</TransactionAmount></Transaction><TransactionSetup><TransactionSetupMethod>1</TransactionSetupMethod><Embedded>1</Embedded><AutoReturn>1</AutoReturn><ReturnURL>Obsfucated</ReturnURL><CustomCss>body{margin-left:50px;font-family:arial;font-size:large;border:none;}</CustomCss></TransactionSetup></TransactionSetup>',
        guid;
    $.ajax({
        type: 'POST',
        url: 'webserviceurl',
        contentType: "application/json; charset=utf-8",
        dataType: "xml",
        data: JSON.stringify({
            Action: $('#Action').val(),
            IsAjax: $('#IsAjax').val(),
            xml: xmlStr,
        }),
        success: function(response) {
            guid = response;
            console.log('success' + guid);
        },
        error: function (jqXHR, tranStatus, errorThrown) {
        console.log(
            'Status: ' + jqXHR.status + ' ' + jqXHR.statusText + '. ' +
            'Response: ' + jqXHR.responseText
        );
    }
    });

I've created a sample at this link https://jsfiddle.net/b6f4tuyx/1/, you could check it.



来源:https://stackoverflow.com/questions/42121931/xml-name-cannot-begin-with-the-character

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!