1

次のように、xml をキーと値のペアのマップに解析しようとしています。

サンプル XML ドキュメント:

<Students>
    <StudentA>
        <Id>123</Id>
        <Address>123 W </Address>
        <Courses>
            <Course1>CS203</Course1>
            <Course2>CS206</Course2>
        </Courses>
    </StudentA>
    <StudentB>
        <Id>124</Id>
        <Address>124 W </Address>
        <Courses>
            <Course1>CS202</Course1>
            <Course2>CS204</Course2>
        </Courses>
    </StudentB>
</Students>

xml パーサー コード:

/**
 * Parse the given xml data.
 * @param xmlString The xml string to be parsed.
 * @return Non-null list of {@link DiscreteDataEntry} values, may be empty.
 */
Map<String, String> parseXML(final String xmlString)
{
    final String xmlDataToParse = xmlString;

    parentNode = "";
    try
    {
        final InputStream inputStream = new ByteArrayInputStream(xmlDataToParse.getBytes());
        final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        final DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        final Document document = documentBuilder.parse(inputStream);
        final Map<String, String> data = createMapOfAttributeValuesKeyedByName(document.getDocumentElement());
    }
    catch (final Exception exception)
    {
        System.out.println("Exception:" + exception);
    }

    return data;
}

/**
 * A recursive method which will loop through all the xml nodes.
 * @param node The node.
 * @return Non-null map of test values keyed by test name, may be empty.
 */
Map<String, String> createMapOfAttributeValuesKeyedByName(final Node node)
{
    final Map<String, String> attributeValuesKeyedByName = new LinkedHashMap<String, String>();
    final NodeList nodeList = node.getChildNodes();
    for (int index = 0; index < nodeList.getLength(); index++)
    {
        final Node currentNode = nodeList.item(index);
        if (node.getFirstChild() != null && node.getFirstChild().getNodeType() == Node.ELEMENT_NODE)
        {
            parentNode = getAncestralOrigin(currentNode);
            attributeValuesKeyedByName.putAll(createMapOfAttributeValuesKeyedByName(currentNode));
        }
        else if (node.getFirstChild() != null && node.getFirstChild().getNodeType() == Node.TEXT_NODE)
        {
            final String attributeName = parentNode.length() > 0 ? parentNode + "." + node.getNodeName().trim() : node.getNodeName().trim();
            final String attributeValue = node.getTextContent().trim();
            attributeValuesKeyedByName.put(attributeName, attributeValue);
            parentNode = "";
        }
    }

    return attributeValuesKeyedByName;
}

/**
 * Parses a give node and finds all its ancestors.
 * @param node The node whose ancestors have to be found.
 * @return A non-null but possible empty string built using the ancestors of the node.
 */
final String getAncestralOrigin(final Node node)
{
    String ancestralOrigin = "";
    final Node currentParentNode = node.getParentNode();
    if (currentParentNode != null && currentParentNode.getNodeType() != Node.DOCUMENT_NODE)
    {
        ancestralOrigin = currentParentNode.getNodeName();
        final String ancestor = getAncestralOrigin(currentParentNode);
        if (ancestor.length() > 0)
        {
            ancestralOrigin = ancestor + "." + ancestralOrigin;
        }
    }
    return ancestralOrigin;
}

マップの出力は次のとおりです。

Key:[Students.StudentA.Id], Value:[123]
Key:[Students.StudentA.Address], Value:[123 W]
Key:[Students.StudentA.Courses.Course1], Value:[CS203]
Key:[Students.StudentA.Courses.Course2], Value:[CS206]
Key:[Students.StudentB.Id], Value:[124]
Key:[Students.StudentB.Address], Value:[124 W]
Key:[Students.StudentB.Courses.Course1], Value:[CS202]
Key:[Students.StudentB.Courses.Course2], Value:[CS204]

ただし、ファイルが次のコマンドで読み取られている場合、この出力は正常に機能します

final BufferedReader bufferedReader = new BufferedReader(new FileReader(new     File(url.getFile().replaceAll("%20", " "))));

同じファイルが読み込まれた場合

DataInputStream is = new DataInputStream(new FileInputStream(new File(url.getFile().replaceAll("%20", " "))));

出力が異なります。xml doc 内のすべての CR と LF を取ります。

キー:[学生]、値:[123 123 W

        CS203
        CS206



    124
    124 W 

        CS202
        CS204]

DataInputStream を使用する xml ファイルを読み取るために、依存関係の jar を使用しています。

私は常に、xml パーサーが CR/LF/NewLine のように見えるのを処理するという印象を受けていました。解析する前に、すべての CR LF と NewLines を空の文字列に置き換えています。

しかし、それ自体を処理する他の xml パーサーがあるかどうかを知りたいです。また、BufferedReader が CR/LF と NewLine をスキップする背後にある理由は何ですか。

また、子タグの祖先を見つけるための他の良い方法はありますか?キー値を一意にするためにそれらが必要です。

xml はそのままで、変更できません。また、xml はここに示されているものと同じではなく、タグが変更された汎用 xml になるため、xml の子タグを解析してそれらをマップに配置する汎用 xml パーサーを作成しようとしています。

子タグは複製できるため、子へのパスを使用して一意にしています。

また、親タグの学生を削除することにより、これらのタグ (StudentA/StudentB) だけで xml を再帰的に解析する方法もあります。

注: xml 形式が変更され、解析する xml が xml ファイルごとに変更される可能性があります。したがって、StudentA の子を取得するように解析することはできません。

4

2 に答える 2

0

長い説明を読んだ後、XML を解析するための他のより良い方法を知りたがっていることがわかりました。

答えは、はい、XML を解析するためのより良い方法が他にあるということです。StAXまたはを使用SAXします。これらは高速で、メモリ効率が高くなります。詳細JAXPについては、Java チュートリアルを参照してください。

于 2013-06-27T17:53:17.750 に答える
0

DataInputStreamを使用して記述されたもののみを読み取ることを目的としていDataOutputStreamます...つまり、シリアライズされた Java オブジェクト。テキスト入力を読み取るためのものではありません。

于 2013-06-27T18:38:50.393 に答える