简体   繁体   中英

How can I remove a namespace from an XML document?

In my Flex application, I call several .NET WebServices that return XML. However, these WebServices all return XML with a namespace. I cannot read/parse the XML without referencing the namespace, meaning that I have to include the following lines of code in each Class that calls a WebService:

private namespace PCRWebServices = "xxx.somename.web.services";

use namespace PCRWebServices;

I would like to eliminate the need for this static/hard-coded logic simply to read XML from a WebService.

Is there any way to "remove" the namespace from the XML, so that I can read it as a "normal" XML document?

I have a Class that I extend for every WebService call that handles results and faults:

private function faultHandler(event:FaultEvent):void
{

}

private function resultHandler(event:ResultEvent):void
{
    var resultXML:XML = new XML(event.result);
}

I would like to add some logic to the result handler to "convert" the XML. Any ideas?

This what trace(resultXML) returns:

<GetDataResult xmlns="xxx.somename.web.services">
  <DataSet>
    <Data>
      <IdNmb>15</IdNmb>
      <NameTxt>Hello</NameTxt>
    </Data>
    <Data>
      <IdNmb>16</IdNmb>
      <NameTxt>World</NameTxt>
    </Data>
    <Status>
      <Status>Success</Status>
    </Status>
    <ReturnCode>
      <ReturnCode>0</ReturnCode>
    </ReturnCode>
  </DataSet>
</GetDataResult>

Here's another regex solution. It will remove multiple namespaces, not just one.

private function resultHandler(event:ResultEvent):void
{
    var nsRegEx:RegExp = new RegExp(" xmlns(?:.*?)?=\".*?\"", "gim");

    var resultXML:XML = new XML(String(event.result).replace(nsRegEx, ""));        
}

Try the solution below. I found it better than replacing the string with regexp.

replaceDefaultNameSpace(src, new Namespace()); //no uri
replaceDefaultNameSpace(src, new Namespace("", "http://uri.com")); //with uri


private function replaceDefaultNameSpace (src:XML, ns:Namespace):void
    {
        var tempNs:Namespace = new Namespace ("temp");
        var node:XML;

        src.addNamespace(tempNs);
        src.setNamespace(tempNs);

        for each (node in src.descendants()) node.setNamespace(tempNs);

        src.addNamespace(ns);
        src.setNamespace(ns);

        for each (node in src.descendants()) node.setNamespace(ns);

        src.removeNamespace(tempNs);

        trace (src.toXMLString());

    }

I found this workaround, using RegEx to remove the namespaces from the XMLString.

http://brianmriley.wordpress.com/2008/03/14/remove-xml-namespaces-in-flex-or-as3/

Here is how I implemented it:

private function resultHandler(event:ResultEvent):void
{
    var resultXML:XML = 
        removeDefaultNamespaceFromXML(new XML(event.result));

    // play with your XML here
}

private function removeDefaultNamespaceFromXML(xml:XML):XML
{
    var rawXMLString:String = xml.toXMLString();

    /* Define the regex pattern to remove the default namespace from the 
        String representation of the XML result. */
    var xmlnsPattern:RegExp = 
        new RegExp("xmlns=[^\"]*\"[^\"]*\"", "gi");

    /* Replace the default namespace from the String representation of the 
        result XML with an empty string. */
    var cleanXMLString:String = rawXMLString.replace(xmlnsPattern, "");

    // Create a new XML Object from the String just created
    return new XML(cleanXMLString);
}

I tried a few of the solutions posted here with marginal success.
Here's what worked for me...

var myXML:XML = new XML(myString);
for each ( var ns:Namespace in myXML.namespaceDeclarations() ) {
    if (ns.prefix == 'my_namespace_prefix' || ns.uri == 'my_namespace_uri') {
        myXML.removeNamespace( new Namespace(ns.prefix, ns.uri) );
    }
}

You can leave out the conditional to remove all namespaces.

I found creating a new Namespace object to be necessary because if you pass in the ns variable as-is, it seems to be coerced to a String, which returns the uri property, which had the effect of leaving the prefixes in my XML data.

I found it necessary to add this next code block, as well, to remove all traces of the original namespaces (running the above code produced strange "aaa" namespaces after namespace removal).

myXML.setNamespace('');
for each (var node:XML in myXML.descendants()) {
    node.setNamespace('');
    for each (var attribute:XML in node.attributes()) {
        attribute.setNamespace('');
    }
}

I wouldn't use the hacks that remove namespaces from the xml as a string. That is a ugly hack (and not to mention inefficient). What you can do to avoid hardcoding the namespace in your code is to ask the xml object what it's default namespace is and use that. Like this:

var defaultNS:Namespace = xml.namespace("");  // get default namespace
use namespace defaultNS;  // use default ns

While I agree that the appropriate way to interact with the XML is by addressing it through its namespace, when you are intentionally trying to translate or convert content from XML of one namespace to another (for example, FXG to MXML) sometimes you have to get down and dirty and hack the XML as a string. This is by no means the most elegant and if there is a more correct way of doing this I am open to it. Unfortunately, from what I've read, it looks like you can't remove the default or last namespace from an XML object.

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/XML.html#removeNamespace%28%29

When you specify use namespace you are setting that as the default namespace, instead of calling that you can pass the namespace when you try to access an element

var myval:String = PCRWebServices::node.@attribute;

I remember having some problems with this. Can't remember excatly how I solved, but I'm guessing the removeNamespace function would be a good start. Maybe something like:

private function resultHandler(event:ResultEvent):void
{
    var resultXML:XML = new XML(event.result);

    for each( var ns:Namespace in resultXML.namespaceDeclarations() )
        resultXML.removeNamespace(ns);
}

I haven't tested the code at all, just from the top of my head.

You can read more here: http://help.adobe.com/en_US/AS3LCR/Flash_10.0/XML.html#removeNamespace()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM