<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Dengues Studio: Google Group:http://groups.google.com/group/dengues; QQ Group:24885404.
    解析一個(gè)XML文件有很多方法,最常用的就是Dom4j,和JDOM.這個(gè)我們就是講使用Xalan來解析一個(gè)XML文件.
    先有個(gè)xml文件如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <a:main xmlns="test0" xmlns:a="testt" xmlns:b="test2">
        
    <a:node>
            
    <a:nodeA1>A1</a:nodeA1>
            
    <a:nodeA2>
                
    <b:nodeB>B1</b:nodeB>
                
    <b:nodeB>B2</b:nodeB>
            
    </a:nodeA2>
        
    </a:node>
        
    <node>
            
    <nodeD/>
        
    </node>
    </a:main> 
    這個(gè)一個(gè)簡單的xml文件.但是我們現(xiàn)在要用xpath來查找
    "/a:main/node"
    一般你是一個(gè)很復(fù)雜的表達(dá)式,這個(gè)xpath是經(jīng)過簡化的.簡化的代碼你可以使用如下:
     1 private static String simplifyXPathExpression(String xpathExpression) {
     2 
     3         Perl5Matcher matcher = new Perl5Matcher();
     4 
     5         Perl5Compiler compiler = new Perl5Compiler();
     6 
     7         Pattern pattern = null;
     8         try {
     9             pattern = compiler.compile("(.*)/\\s*\\w+\\s*(/(\\.\\.|parent))(.*)");
    10         } catch (MalformedPatternException e) {
    11             ExceptionHandler.process(e);
    12         }
    13 
    14         Perl5Substitution substitution = new Perl5Substitution("$1$4", Perl5Substitution.INTERPOLATE_ALL);
    15 
    16         int lengthOfPreviousXPath = 0;
    17 
    18         do {
    19             lengthOfPreviousXPath = xpathExpression.length();
    20             if (matcher.matches(xpathExpression, pattern)) {
    21                 xpathExpression = Util.substitute(matcher, pattern, substitution, xpathExpression, Util.SUBSTITUTE_ALL);
    22             }
    23         } while (xpathExpression.length() != lengthOfPreviousXPath);
    24 
    25         return xpathExpression;
    26     }
    這里使用的org.apache.oro.text.regex包里面的類.
    現(xiàn)在就開始解析一個(gè)XML文件:在Dengues 項(xiàng)目中的org.dengues.commons.jdk.xpath.ComplexXPathUsedXalan類.
     1 public ComplexXPathUsedXalan(String xmlFilename) {
     2         xmlInput = new File(xmlFilename);
     3         if (!xmlInput.exists()) {
     4             throw new RuntimeException("Specified file does not exist!");
     5         }
     6         try {
     7             DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
     8             docFactory.setNamespaceAware(true);
     9             DocumentBuilder builder = docFactory.newDocumentBuilder();
    10             document = builder.parse(xmlInput);
    11             initLastNodes(document.getDocumentElement());
    12             prefixToNamespace.put(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI);
    13         } catch (ParserConfigurationException e) {
    14             e.printStackTrace();
    15         } catch (IOException e) {
    16             e.printStackTrace();
    17         } catch (SAXException exception) {
    18             exception.printStackTrace();
    19         }
    20         XPathFactory factory = XPathFactory.newInstance();
    21         xPath = factory.newXPath();
    22         xPath.setNamespaceContext(getNamespaceContext());
    23     }
    這是類的構(gòu)造函數(shù).這里要注意的幾個(gè)地方就是:1.第8行設(shè)置這個(gè)DocFactory支持Namespace.這里一定要設(shè)置否則你將不能找所需要的節(jié)點(diǎn).
    2.在第12行,此前我新建了一個(gè)Map用來存儲(chǔ)Prefix和Namespace的對應(yīng)關(guān)系:
    1 private final Map<String, String> prefixToNamespace = new HashMap<String, String>();
    在12行就是講XML對應(yīng)Namespace設(shè)置進(jìn)去.
    3.第11行,它的作用的就是取出所有的Prefix和Namespace.代碼如下:
     1 private void initLastNodes(Node node) {
     2         NodeList childNodes = node.getChildNodes();
     3         int length = childNodes.getLength();
     4         int type = node.getNodeType();
     5         if (type == Node.ELEMENT_NODE) {
     6             setPrefixToNamespace(node);
     7         }
     8         for (int i = 0; i < length; i++) {
     9             Node item = childNodes.item(i);
    10             if (item.getChildNodes().getLength() > 0) {
    11                 initLastNodes(item);
    12             }
    13         }
    14     }
    15 
    16     /**
    17      * DOC qzhang Comment method "setPrefixToNamespace".
    18      * 
    19      * @param node
    20      */
    21     private void setPrefixToNamespace(Node node) {
    22         NamedNodeMap nnm = node.getAttributes();
    23         for (int i = 0; i < nnm.getLength(); i++) {
    24             Node attr = nnm.item(i);
    25             String aname = attr.getNodeName();
    26             boolean isPrefix = aname.startsWith(XMLConstants.XMLNS_ATTRIBUTE + ":");
    27             if (isPrefix || aname.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
    28                 int index = aname.indexOf(':');
    29                 String p = isPrefix ? aname.substring(index + 1) : XMLConstants.NULL_NS_URI;
    30                 prefixToNamespace.put(p, attr.getNodeValue());
    31             }
    32         }
    33     }
    這樣的就可以去到當(dāng)前XML的所有Prefix的所有節(jié)點(diǎn).
    4.其實(shí)去Prefix和Namepace還由另外的API:com.sun.org.apache.xml.interal.utils.PrefixResloverDefault,你可以使用它:
    1  PrefixResolverDefault resolverDefault = new PrefixResolverDefault(document.getDocumentElement());
    2        String namespace = resolverDefault.getNamespaceForPrefix(prefix);
    你可以使用這種方法.但是我覺得這種方法在大部分情況下解決不了問題.原因:(1)當(dāng)前你只有document的根結(jié)點(diǎn).也就是說它只能得到根結(jié)點(diǎn)定義的Namespace.(2)當(dāng)根結(jié)點(diǎn)也使用了Namespace的話(a:main),解析就有問題.
    5.構(gòu)造函數(shù)的22行設(shè)置一個(gè)NamespaceContext,代碼如下:
     1 private NamespaceContext getNamespaceContext() {
     2         return new NamespaceContext() {
     3 
     4             public String getNamespaceURI(String prefix) {
     5                 String namespaceForPrefix = getNamespaceForPrefix(prefix);
     6                 return namespaceForPrefix;
     7 
     8             }
     9 
    10             public java.util.Iterator getPrefixes(String val) {
    11                 return null;
    12             }
    13 
    14             public String getPrefix(String uri) {
    15                 return null;
    16             }
    17         };
    18     }
    19 
    20     /**
    21      * DOC qzhang Comment method "getNamespaceForPrefix".
    22      * 
    23      * @param prefix
    24      * @return
    25      */
    26     protected String getNamespaceForPrefix(String prefix) {
    27         String namespace = prefixToNamespace.get(prefix);
    28         if (namespace != null) {
    29             return namespace;
    30         }
    31         return getDefaultNamespace();
    32     }
    33 
    34     private String getDefaultNamespace() {
    35         Node parent = document.getDocumentElement();
    36         int type = parent.getNodeType();
    37         if (type == Node.ELEMENT_NODE) {
    38             NamedNodeMap nnm = parent.getAttributes();
    39             for (int i = 0; i < nnm.getLength(); i++) {
    40                 Node attr = nnm.item(i);
    41                 String aname = attr.getNodeName();
    42                 if (aname.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
    43                     return attr.getNodeValue();
    44                 }
    45             }
    46         }
    47         return XMLConstants.NULL_NS_URI;
    48     }
    這個(gè)總要就是取Namespace值,但是當(dāng)你輸入Prefix不在Map里面的時(shí)候,它將取默認(rèn)的Namespace,也就是在getDefaultNamespace().
    現(xiàn)在就是最后要提供一個(gè)API:
     1 public Object parseXPath(String expression, QName name) {
     2         try {
     3             expression = addDefaultPrefix(expression);
     4             XPathExpression xexpr = xPath.compile(expression);
     5             Object cd = xexpr.evaluate(getDocumnent(), name);
     6             return cd;
     7         } catch (XPathExpressionException e) {
     8             e.printStackTrace();
     9         }
    10         return null;
    11     }
    12 
    13     private String addDefaultPrefix(String xPathExpression) {
    14         if (XMLConstants.NULL_NS_URI.equals(getDefaultNamespace())) {
    15             return xPathExpression;
    16         } else {
    17             StringBuilder expr = new StringBuilder();
    18             String[] split = xPathExpression.split("/");
    19             for (String string : split) {
    20                 if (!string.equals(""&& string.indexOf(':'== -1 && string.indexOf('.'== -1) {
    21                     expr.append(XMLConstants.DEFAULT_NS_PREFIX + ":");
    22                 }
    23                 expr.append(string + "/");
    24             }
    25             if (split.length > 0) {
    26                 expr.deleteCharAt(expr.length() - 1);
    27             }
    28             return expr.toString();
    29         }
    30     }

    這個(gè)就是提供的解析xpath表達(dá)是的接口.大家會(huì)看到了要執(zhí)行一個(gè)添加addDefaultPrefix()的函數(shù),它的作用就是在
    當(dāng)存在默認(rèn)Namespace的時(shí)候,添加一個(gè)默認(rèn)的Prefix.這樣的問題解決了.
    再看看測試的代碼:
     1 private static void testXPath() {
     2         ComplexXPathUsedXalan complexXPath = new ComplexXPathUsedXalan("c:/SimpleNamespace.xml");
     3         String expression = "/a:main/node";
     4         try {
     5             NodeList nodes = (NodeList) complexXPath.parseXPath(expression, XPathConstants.NODESET);
     6             System.out.println("length: " + nodes.getLength());
     7             for (int i = 0; i < nodes.getLength(); i++) {
     8                 Node item = nodes.item(i);
     9                 System.out.println("Name:" + item.getNodeName() + " value:" + item.getNodeValue());
    10             }
    11         } catch (Exception e) {
    12             e.printStackTrace();
    13         }
    14     }
    這樣就可以得到打印結(jié)果:
    1 length: 1
    2 Name:node value:null
    就是這樣了.歡迎大家指正.



    Dengues論壇(http://groups.google.com/group/dengues/),一個(gè)很好的Eclipse開發(fā)者樂園.

    Feedback

    # re: [Dengues]關(guān)于使用XPath的勸解.帶有Namespace的.  回復(fù)  更多評論   

    2007-11-06 16:46 by zDevil(Dengues Studio)
    不好意思,標(biāo)題都寫錯(cuò)了,應(yīng)該是講解.^_^!

    # re: [Dengues]關(guān)于使用XPath的勸解.帶有Namespace的.  回復(fù)  更多評論   

    2007-11-06 17:41 by li
    恰好今天在項(xiàng)目中也用到dom4j和jaxen,不過在Xpath時(shí)候遇到不能能解析命名空間的的問題,沒有好的辦法就去掉了命名空間,呵呵
    以后重新試試

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    Dengues Studio: Google Group:http://groups.google.com/group/dengues; QQ Group:24885404.
    主站蜘蛛池模板: 亚洲日本精品一区二区| 免费无码又爽又高潮视频| 免费看搞黄视频网站| 最近免费字幕中文大全| 丁香花在线观看免费观看图片| 曰批全过程免费视频观看免费软件| 99亚洲乱人伦aⅴ精品| 亚洲精品色在线网站| 羞羞漫画页面免费入口欢迎你 | 日本无吗免费一二区| 国产男女猛烈无遮挡免费视频 | 久久精品成人免费看| 久久午夜夜伦鲁鲁片免费无码| 午夜免费福利小电影| 最近中文字幕2019高清免费| 国产91免费在线观看| 免费人成视频在线| 国产免费人成视频在线观看| 亚洲人成网站在线观看青青| 亚洲综合无码精品一区二区三区| 亚洲AV中文无码乱人伦下载 | 亚洲欧洲日产国码无码网站 | 亚洲中文无韩国r级电影 | 在线观看免费毛片| 国产小视频在线观看免费| 亚洲乱码国产一区网址| 亚洲精品~无码抽插| 亚洲无线电影官网| 亚洲偷自精品三十六区| 老外毛片免费视频播放| 最近更新免费中文字幕大全| 成人免费的性色视频| 国产乱子伦精品免费女| 亚洲一区二区三区在线观看精品中文| 久久亚洲AV无码精品色午夜麻| 亚洲国产综合在线| 精品国产亚洲AV麻豆| 国产一级淫片a免费播放口| 2020久久精品国产免费| 亚洲不卡AV影片在线播放| 亚洲产国偷V产偷V自拍色戒|