0

dom4j を使用して XML メッセージ処理プログラムを作成していて、XML ノード属性の解析で問題が発生しました。ビジネス要件は次のとおりです。入力 XML を解析して検証し、フィールドまたは属性が無効な場合は、構造がエラーを示す XML を返します。そして、私は以下のテストプログラムを切り取りました:

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class XPathStudy {
    private final static Logger log = LoggerFactory.getLogger(XPathStudy.class);
    private static String xmlInput;

    private static void initXmlInput() {
        xmlInput = "<RootTag> <BizRec FLAG=\"5\">";
        xmlInput += " <FieldOne>11111</FieldOne>";
        xmlInput += " <FieldTwo></FieldTwo>";
        xmlInput += " <FieldThree>33333</FieldThree>";
        xmlInput += " </BizRec> </RootTag>";
    }

    private static Document makeErrRspsDoc(String xpath, String errCode, String errDesc) {
        Document errDoc = DocumentHelper.createDocument();
        Element errElem = DocumentHelper.makeElement(errDoc, xpath);
        errElem.addElement("ErrCode").addText(errCode);
        errElem.addElement("ErrDesc").addText(errDesc);
        return errDoc;
    }

    public static void main(String[] args) throws Exception {
        initXmlInput();
        log.info("xmlInput = " + xmlInput);
        Document doc = DocumentHelper.parseText(xmlInput);
        log.info("xmlInput parsed done");

        String xpath = "*//FieldTwo";
        Node node = doc.getRootElement().selectSingleNode(xpath);
        if (node == null) {
            log.warn("node [" + xpath + "] not found");
            System.exit(1);
        }
        log.info("node [" + node.getPath() + "] located");
        if (node.getText().trim().isEmpty()) {
            Document errDoc = makeErrRspsDoc(node.getPath(), "1201", "FieldTwo can not be empty");
            log.warn("errDoc: " + errDoc.asXML());
        } else {
            log.info("FieldTwo validation ok");
        }

        xpath = "*//@FLAG";
        node = doc.getRootElement().selectSingleNode(xpath);
        if (node == null) {
            log.warn("node [" + xpath + "] not found");
            System.exit(1);
        }
        log.info("node [" + node.getPath() + "] located");
        int flagVal = Integer.parseInt(node.getText().trim());
        if (flagVal == 1 || flagVal == 2) {
            log.info("FLAG " + flagVal + " is ok");
        } else {
            Document errDoc = makeErrRspsDoc(node.getPath(), "1001", "FLAG attr should be 1 or 2");
            log.warn("errDoc: " + errDoc.asXML());
        }
    }
}

それを実行すると、以下のログ情報が表示されます。

15:01:08.143 [main] INFO  XPathStudy - xmlInput = <RootTag> <BizRec FLAG="5"> <FieldOne>11111</FieldOne> <FieldTwo></FieldTwo> <FieldThree>33333</FieldThree> </BizRec> </RootTag>
15:01:08.203 [main] INFO  XPathStudy - xmlInput parsed done
15:01:08.255 [main] INFO  XPathStudy - node [/RootTag/BizRec/FieldTwo] located
15:01:08.259 [main] WARN  XPathStudy - errDoc: <?xml version="1.0" encoding="UTF-8"?>
<RootTag><BizRec><FieldTwo><ErrCode>1201</ErrCode><ErrDesc>FieldTwo can not be empty</ErrDesc></FieldTwo></BizRec></RootTag>
15:01:08.260 [main] INFO  XPathStudy - node [/RootTag/BizRec/@FLAG] located
15:01:08.260 [main] WARN  XPathStudy - errDoc: <?xml version="1.0" encoding="UTF-8"?>
<RootTag><BizRec><@FLAG><ErrCode>1001</ErrCode><ErrDesc>FLAG attr should be 1 or 2</ErrDesc></@FLAG></BizRec></RootTag>

すべて問題ないようで、errDoc は Oracle10g テーブル (VARCHAR2(1000) フィールド) に記録されます。次の SQL は問題ありません。

select extractvalue(xmltype('<RootTag><BizRec><FieldTwo><ErrCode>1201</ErrCode><ErrDesc>FieldTwo can not be empty</ErrDesc></FieldTwo></BizRec></RootTag>'),
'*//ErrCode') as err_code from dual;
1201

しかし、次の SQL は失敗します。

select extractvalue(xmltype('<RootTag><BizRec><@FLAG><ErrCode>1001</ErrCode><ErrDesc>FLAG attribute should be 1 or 2</ErrDesc></@FLAG></BizRec></RootTag>'),
'*//ErrCode') as err_code from dual;

Error starting at line 1 in command:
select extractvalue(xmltype('<RootTag><BizRec><@FLAG><ErrCode>1001</ErrCode><ErrDesc>FLAG attribute should be 1 or 2</ErrDesc></@FLAG></BizRec></RootTag>'),
'*//ErrCode') as err_code from dual
Error report:
SQL Error: ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00231: invalid character 64 ('@') found in a Name or Nmtoken
Error at line 1
ORA-06512: at "SYS.XMLTYPE", line 301
ORA-06512: at line 1
31011. 00000 -  "XML parsing failed"
*Cause:    XML parser returned an error while trying to parse the document.
*Action:   Check if the document to be parsed is valid.

また、Oracle のドキュメントでは、XML のノードに特殊文字を含めることはできないと説明しています。だから、私の質問は次のとおりです。「FLAG」属性のエラー応答の問題を解決するために Java コードを変更するにはどうすればよいですか?

4

1 に答える 1

1

<@FLAG>@文字を名前の先頭にすることはできないため、は有効なXML要素名ではありません。DOM4Jは、整形式で有効なXMLドキュメントを適用する場合にクラス最高であることで知られていません。

失敗したノードをXPath式として通信するには、属性またはテキストノードに格納することを検討してください。

于 2012-08-06T22:01:44.440 に答える