【问题标题】:Parse "Non-Standard" XML with Javascript?用 Javascript 解析“非标准”XML?
【发布时间】:2014-08-04 17:51:07
【问题描述】:

下午好,

我正在尝试使用严格的 Javascript 解析 XML 文件(由于此代码所在的模块中的内存限制,我宁愿不使用诸如 jQuery 之类的附加组件)。 XML 文件由我在装配线控制器中的控制系统中的一个模块填充,因此我认为该格式与典型的 XML 文件略有不同。我可以正确加载文件(我使用警报查看原始文本输出并且它是正确的),但我无法加载标签的值。加载的部分 XML 文件如下:

<tag name = "Parts_Built_Buffer[490].DateTime" valueType="cip:dt_STRINGI" path="1,0" access="read" display="String">
    <value xsi:type="cip:dt_STRINGI">20140804110319</value>
</tag>

它会持续 500 个这样的标签...由于模块要求的性质,每个标签都有一个唯一的名称,所以我想遍历所有标签以获取值并构建一个表。为此,我的代码(减去循环部分,因为我需要在运行(加载所有值)之前抓取(加载 1 个值))是:

var builtDataView_url = "/user/system/dataviews/Parts_Built_Buffer.xml";

    var getDataView = new XMLHttpRequest();
    getDataView.open("GET", builtDataView_url, false);
    getDataView.send();
    var builtXML = getDataView.responseXML;
    alert("response is " + getDataView.responseText)

    var job0 = builtXML.getElementsByTagName("/tag[Name='Parts_Built_Buffer[0].DateTime']/value")[0];
    alert("job0 is " + job0)

在第一个警报中,我得到了 XML 的文本视图,它按预期显示。但是,对于 job0,我知道它是未定义的(如果我提醒 job0.length 我得到 0)。我需要这个在 Chrome 和 IE 中工作。任何建议将不胜感激。

编辑: 我今天必须在控制台上玩一些(我昨天和今天早上没时间)返回数据。我对 javascript 相当陌生,并且是自学(即 Google)。控制台对话框如下,返回的 XML 未将 value 标签与 parts_built... 标签分组。由于我是新手,如果函数调用没有意义,请不要取笑我读取数据的尝试,请...

data.getElementsByTagName("*")
HTMLCollection[101]
data.getElementsByTagName("*")[0]
<view xmlns:xsi=​"http:​/​/​www.w3.org/​2001/​XMLSchema-instance" xmlns=​"http:​/​/​    www.rockwellautomation.com/​technologies/​data_access/​data_views/​1.0/​" xmlns:cip=​"http:​/​/​www.rockwellautomation.com/​technologies/​data_access/​data_types/​1.0/​" xsi:schemaLocation=​"http:​/​/​www.rockwellautomation.com/​technologies/​data_access/​data_views/​1.0/​ /​schema/​  dataview.xsd" name=​"EWEB_Data" description>​…​</view>​
data.getElementsByTagName("*")[1]
<tag name=​"Parts_Built_Buffer[490]​.DateTime" valueType=​"cip:​dt_STRINGI" path=​"1,0"    access=​"read" display=​"String">​
<value xsi:type=​"cip:​dt_STRINGI">​20140805111641​</value>​
</tag>​
data.getElementsByTagName("*")[1].value
undefined
data.getElementsByTagName("*")[2]
<value xsi:type=​"cip:​dt_STRINGI">​20140805111641​</value>​
data.getElementsByTagName("*")[3]
<tag name=​"Parts_Built_Buffer[490]​.VIN" valueType=​"cip:​dt_STRINGI" path=​"1,0" access=​    "read" display=​"String">​…​</tag>​
data.getElementsByTagName("*")[4]
<value xsi:type=​"cip:​dt_STRINGI">​</value>​
data.getElementsByTagName("*")[5]
<tag name=​"Parts_Built_Buffer[490]​.SerNum" valueType=​"cip:​dt_STRINGI" path=​"1,0"     access=​"read" display=​"String">​
<value xsi:type=​"cip:​dt_STRINGI">​643Y037S14217​</value>​
</tag>​
data.getElementsByTagName("*")[6]
<value xsi:type=​"cip:​dt_STRINGI">​643Y037S14217​</value>​
data.getElementsByTagName("*")[5].getElementsByTagName("*")
[
<value xsi:type=​"cip:​dt_STRINGI">​643Y037S14217​</value>​
]
data.getElementsByTagName("tag name*")[5].getElementsByTagName("*")
TypeError: Cannot read property 'getElementsByTagName' of undefined
data.getElementsByTagName("Parts_Built_Buffer*")[5].getElementsByTagName("*")
TypeError: Cannot read property 'getElementsByTagName' of undefined

此代码将产生值(请记住,我只关心偶数标记索引,因为它们保存值... data.getElementsByTagName("*")[6].textContent

这似乎很笨拙,所以任何建议仍然会受到赞赏...至少看起来我不必从文本输出开始并解析一个长文本字符串...

【问题讨论】:

  • /tag[Name='... 替换为/tag[name='... 是否有帮助(即更改N 的大小写?)
  • 没有。它以“job0 is [object HTMLCollection]”作为响应(这将是脚本中的第二个警报,就在尝试读取第一个标签之后)。
  • 您是否必须保留与封闭的“标签”标签关联的值?如果没有,RegEx 可能比尝试解析非标准 XML 更容易。
  • 我不关注你的问题...我想知道我使用的是什么值,但我想只要我假设 XML 文件总是以相同的顺序出现(其中它应该)然后我可以索引所有节点并相应地分配它们......

标签: javascript xml parsing


【解决方案1】:

您可以使用标准 DOM 属性:childNodesfirstChildnextSibling

因此,我将导航到包含所有标签的节点,然后在childNodes 上使用for 循环。类似的东西:

var main_node = something;
var table = {};
for (var i = 0; i < main_node.childNodes.length; i++) {
    var node = main_node.childNodes[i];
    if (node.nodeType == 1) {
        // Insert your code here.
        var name = node.getAttribute('name');
        var value = writeYourFunctionToExtractValueFromNode(node);
        table[name] = value;
    }
}

// After the pre-processing step above, you can just use:
alert(table['Parts_Built_Foobar']);

nodeType 的检查是跳过 cmets、空白和其他不相关的节点。

我在这里提到的所有内容都只是标准 DOM,并且基本上可以在任何地方使用(包括 JavaScript 以外的其他语言)。

【讨论】:

  • 我认为这是我必须走的路。我认为我不能通过标签名称专门搜索,但正如我上面提到的,只要 XML 文件每次都以相同的顺序出现就可以了。我更喜欢按名称搜索(“Parts_Built_Buffer[490].SerNum”),但我无法找到具有该值的标签。如果可以的话,我可以使用 nodeType 评估并做我想做的事。
  • @user3907603,我稍微更新了代码。您可以将循环用作预处理步骤,这将构建一个关联数组,将每个名称映射到相应的值。
猜你喜欢
  • 2011-12-08
  • 2012-10-20
  • 2020-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多