8

我正在使用 matlab 的 xmlread 内部函数读取一个简单的 xml 文件。

<root>
    <ref>
        <requestor>John Doe</requestor>
        <project>X</project>
    </ref>
</root>

但是当我调用ref元素的 getChildren() 时,它告诉我它有5 个孩子。

如果我将所有 XML 放在一行中,它就可以正常工作。Matlab 告诉我ref元素有2 个孩子。

它似乎不喜欢元素之间的空间。

即使我在 oXygen XML 编辑器中运行Canonicalize,我仍然得到相同的结果。因为 Canonicalize 仍然会留下空格。

Matlab 使用 java 和 xerces 处理 xml 内容。

问题:

我该怎么做才能使我的 xml 文件保持人类可读的格式(不是全部在一行中)但仍然让 matlab 正确解析它?

代码更新:

filename='example01.xml';
docNode = xmlread(filename);
rootNode = docNode.getDocumentElement;
entries = rootNode.getChildNodes;
nEnt = entries.getLength
4

2 回答 2

10

幕后的 XML 解析器正在为节点元素之间的所有空白创建 #text 节点。无论哪里有换行符或缩进,它都会在节点的数据部分创建一个带有换行符和缩进空格的#text 节点。因此,在您提供的 xml 示例中,当它解析“ref”元素的子节点时,它返回 5 个节点

  1. 节点 1:#text 带有换行符和缩进空格
  2. 节点 2:“请求者”节点,该节点又在数据部分有一个带有“John Doe”的#text 子节点
  3. 节点 3:#text 带有换行符和缩进空格
  4. 节点 4:“project”节点,该节点又在数据部分有一个带有“X”的#text 子节点
  5. 节点 5:#text 带有换行符和缩进空格

此功能为您删除所有这些无用的#text 节点。请注意,如果您故意让一个 xml 元素仅由空格组成,那么此函数将删除它,但对于 99.99% 的 xml 情况,这应该可以正常工作。

function removeIndentNodes( childNodes )

numNodes = childNodes.getLength;
remList = [];
for i = numNodes:-1:1
   theChild = childNodes.item(i-1);
   if (theChild.hasChildNodes)
      removeIndentNodes(theChild.getChildNodes);
   else
      if ( theChild.getNodeType == theChild.TEXT_NODE && ...
           ~isempty(char(theChild.getData()))         && ...
           all(isspace(char(theChild.getData()))))
         remList(end+1) = i-1; % java indexing
      end
   end
end
for i = 1:length(remList)
   childNodes.removeChild(childNodes.item(remList(i)));
end

end

像这样称呼它

tree = xmlread( xmlfile );
removeIndentNodes( tree.getChildNodes );
于 2012-07-19T01:44:55.397 回答
1

我觉得@cholland 的回答很好,但我不喜欢额外的 xml 工作。因此,这是一种从 xml 文件的副本中去除空格的解决方案,这是不需要元素的根本原因。

fid = fopen('tmpCopy.xml','wt');
str = regexprep(fileread(filename),'[\n\r]+',' ');
str = regexprep(str,'>[\s]*<','><');
fprintf(fid,'%s', str);
fclose(fid);
于 2017-06-19T15:39:57.780 回答