8

matlab の xmlread 内部関数を使用して単純な xml ファイルを読み込んでいます。

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

しかし、要素の getChildren() を呼び出すと、5 つrefの子があることがわかります。

すべての XML を1 行に入れれば問題なく動作します。Matlab は、ref要素に2 つの子があることを教えてくれます。

要素間のスペースが気に入らないようです。

oXygen XML エディターでCanonicalizeを実行しても、同じ結果が得られます。Canonicalize はまだスペースを残すためです。

Matlab は、xml に java と xerces を使用します。

質問:

xml ファイルを人間が読める形式 (すべてが 1 行ではない) に保ちながら、matlab が正しく解析できるようにするにはどうすればよいですか?

コードの更新:

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

2 に答える 2

10

バックグラウンドの XML パーサーは、ノード要素間のすべての空白に対して #text ノードを作成しています。改行またはインデントがある場合は常に、ノードのデータ部分に改行とそれに続くインデント スペースを持つ #text ノードが作成されます。したがって、「ref」要素の子ノードを解析しているときに提供したxmlの例では、5つのノードが返されます

  1. ノード 1: 改行とインデント スペースを含む #text
  2. ノード 2: データ部分に「John Doe」を持つ #text 子を持つ「requestor」ノード
  3. ノード 3: 改行とインデント スペースを含む #text
  4. ノード 4: データ部分に「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 に答える