【问题标题】:How can I remove a namespace from an XML document?如何从 XML 文档中删除命名空间?
【发布时间】:2009-03-23 13:43:55
【问题描述】:

在我的 Flex 应用程序中,我调用了几个返回 XML 的 .NET WebService。但是,这些 Web 服务都返回带有命名空间的 XML。如果不引用命名空间,我就无法读取/解析 XML,这意味着我必须在每个调用 WebService 的类中包含以下代码行:

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

use namespace PCRWebServices;

我想消除这种静态/硬编码逻辑的需要,只需从 WebService 读取 XML。

有没有办法从 XML 中“删除”命名空间,以便我可以将其作为“普通”XML 文档读取?

我为每个处理结果和错误的 WebService 调用扩展了一个类:

private function faultHandler(event:FaultEvent):void
{

}

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

我想在结果处理程序中添加一些逻辑来“转换”XML。有什么想法吗?

这是trace(resultXML) 返回的内容:

<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>

【问题讨论】:

    标签: xml apache-flex actionscript-3 web-services namespaces


    【解决方案1】:

    这是另一个正则表达式解决方案。它将删除多个命名空间,而不仅仅是一个。

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

    【讨论】:

      【解决方案2】:

      我找到了这个解决方法,使用 RegEx 从 XMLString 中删除命名空间。

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

      这是我的实现方式:

      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);
      }
      

      【讨论】:

      • 谢谢。不需要反对,因为这回答了我关于“命名空间”的问题。无论如何我都会支持你的答案。
      • 短一点:var xmlString:String = xml.toXMLString(); xmlString = xmlString.replace(/xmlns="[^"]+"/g, ''); 返回新的 XML(xmlString);
      【解决方案3】:

      尝试以下解决方案。我发现它比用正则表达式替换字符串更好。

      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());
      
          }
      

      【讨论】:

        【解决方案4】:

        当您指定 use namespace 时,您将其设置为默认命名空间,而不是调用它,您可以在尝试访问元素时传递命名空间

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

        【讨论】:

          【解决方案5】:

          我不会使用从 xml 中删除命名空间作为字符串的技巧。这是一个丑陋的黑客(更不用说效率低下)。为了避免在代码中对命名空间进行硬编码,您可以做的是询问 xml 对象它的默认命名空间是什么并使用它。像这样:

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

          【讨论】:

            【解决方案6】:

            虽然我同意与 XML 交互的适当方式是通过其命名空间对其进行寻址,但当您有意尝试将内容从一个命名空间的 XML 转换或转换为另一个命名空间(例如,FXG 到 MXML)时,有时您必须放下并弄脏并将XML作为字符串破解。这绝不是最优雅的,如果有更正确的方法,我愿意接受。 不幸的是,根据我的阅读,您似乎无法从 XML 对象中删除默认名称空间或最后一个名称空间。

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

            【讨论】:

              【解决方案7】:

              我尝试了这里发布的一些解决方案,但都取得了一定的成功。
              这对我有用...

              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) );
                  }
              }
              

              您可以省略删除所有命名空间的条件。

              我发现创建一个新的Namespace 对象是必要的,因为如果您按原样传入ns 变量,它似乎被强制转换为一个字符串,该字符串返回uri 属性,具有效果在我的 XML 数据中保留前缀。

              我发现有必要添加下一个代码块,以删除原始命名空间的所有痕迹(运行上述代码在命名空间删除后会产生奇怪的“aaa”命名空间)。

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

              【讨论】:

                【解决方案8】:

                我记得在这方面遇到了一些问题。不记得我是如何解决的,但我猜 removeNamespace 函数将是一个好的开始。 可能是这样的:

                private function resultHandler(event:ResultEvent):void
                {
                    var resultXML:XML = new XML(event.result);
                
                    for each( var ns:Namespace in resultXML.namespaceDeclarations() )
                        resultXML.removeNamespace(ns);
                }
                

                我根本没有测试过代码,只是从头顶上测试。

                您可以在此处阅读更多内容: http://help.adobe.com/en_US/AS3LCR/Flash_10.0/XML.html#removeNamespace()

                【讨论】:

                • 这会从命名空间声明中删除命名空间,但它仍在 XML 文档中,没有“使用命名空间...”我无法读取 XML 节点。
                • 你说得对,显然它不适用于所有命名空间(请参阅文档)。我将添加一个新的解决方案。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-03-10
                • 2020-12-03
                • 2020-08-30
                • 1970-01-01
                • 2011-03-30
                相关资源
                最近更新 更多