<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來(lái)解析一個(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è)簡(jiǎn)單的xml文件.但是我們現(xiàn)在要用xpath來(lái)查找
    "/a:main/node"
    一般你是一個(gè)很復(fù)雜的表達(dá)式,這個(gè)xpath是經(jīng)過(guò)簡(jiǎn)化的.簡(jiǎn)化的代碼你可以使用如下:
     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包里面的類(lèi).
    現(xiàn)在就開(kāi)始解析一個(gè)XML文件:在Dengues 項(xiàng)目中的org.dengues.commons.jdk.xpath.ComplexXPathUsedXalan類(lèi).
     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     }
    這是類(lèi)的構(gòu)造函數(shù).這里要注意的幾個(gè)地方就是:1.第8行設(shè)置這個(gè)DocFactory支持Namespace.這里一定要設(shè)置否則你將不能找所需要的節(jié)點(diǎn).
    2.在第12行,此前我新建了一個(gè)Map用來(lái)存儲(chǔ)Prefix和Namespace的對(duì)應(yīng)關(guān)系:
    1 private final Map<String, String> prefixToNamespace = new HashMap<String, String>();
    在12行就是講XML對(duì)應(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);
    你可以使用這種方法.但是我覺(jué)得這種方法在大部分情況下解決不了問(wèn)題.原因:(1)當(dāng)前你只有document的根結(jié)點(diǎn).也就是說(shuō)它只能得到根結(jié)點(diǎn)定義的Namespace.(2)當(dāng)根結(jié)點(diǎn)也使用了Namespace的話(huà)(a:main),解析就有問(wèn)題.
    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.這樣的問(wèn)題解決了.
    再看看測(cè)試的代碼:
     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開(kāi)發(fā)者樂(lè)園.

    Feedback

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

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

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

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

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    Dengues Studio: Google Group:http://groups.google.com/group/dengues; QQ Group:24885404.
    主站蜘蛛池模板: 亚洲精品国产免费| 免费播放美女一级毛片| 国产永久免费高清在线| 国产成人综合亚洲AV第一页| free哆拍拍免费永久视频| 亚洲午夜久久久影院| 免费女人高潮流视频在线观看| 亚洲图片一区二区| 中文字幕免费高清视频| 中文无码亚洲精品字幕| 日韩一级在线播放免费观看| 日本亚洲高清乱码中文在线观看| 亚洲综合精品网站| 免费人成毛片动漫在线播放| 亚洲综合小说久久另类区| 西西大胆无码视频免费| 粉色视频在线观看www免费| 麻豆狠色伊人亚洲综合网站| 国产91久久久久久久免费| 成av免费大片黄在线观看| 亚洲精品在线不卡| 亚洲AV无码精品色午夜果冻不卡| 日本免费一区二区在线观看| 青草青草视频2免费观看| 亚洲AV成人片色在线观看高潮 | 亚洲成a人片在线观看日本麻豆| www一区二区www免费| 免费高清A级毛片在线播放| 亚洲AV美女一区二区三区| 久久久久久a亚洲欧洲aⅴ| 青青草国产免费久久久91| 国产在线播放线91免费| 成av免费大片黄在线观看| 久久免费视频网站| 无码精品国产一区二区三区免费 | 男女一边桶一边摸一边脱视频免费| 91亚洲自偷手机在线观看| 免费A级毛片无码A∨男男| 曰批全过程免费视频网址| 99热在线免费播放| 91精品国产免费|