2013-01-22 2 views
-1

XML 문서에서 텍스트 요소의 정확한 XPath를 찾아야합니다. 이 작업을 수행하는 한 가지 방법은 Document를 문자열로 변환하고, 부분 문자열 주위에 임시 태그를 추가하고 Document로 다시 변환 한 다음 XPath를 찾는 것입니다. XML 문서에서 하위 문자열의 XPath 가져 오기

내가 지금까지 무엇을 가지고 :

public String findXPathInXMLString(int startIndex, int endIndex, String string) throws IOException, ParserConfigurationException, SAXException { 
    Conversion conversion = new Conversion(); 
    String xpath; 

    //Step 1. Replace start to end index with temporary tag in string document 
    StringBuilder stringBuilder = new StringBuilder(string); 
    stringBuilder.replace(startIndex, endIndex, "<findXPathInXMLStringTemporaryTag>" + string.substring(startIndex, endIndex) + "</findXPathInXMLStringTemporaryTag>"); 

    //Step 2. Convert string document to DOM document & Find XPath of temporary tag in DOM document 
    xpath = "/" + getXPath(conversion.stringToDocument(stringBuilder.toString()), "findXPathInXMLStringTemporaryTag"); 

    //Step 3. Cut off last part of the XPath 
    //xpath = xpath.substring(0, 2).replace("/documentXPathTemporaryTag", ""); 

    //Step 4. Return the XPath 
    return xpath; 
} 

public String getXPath(Document root, String elementName) { 
    try { 
     XPathExpression expr = XPathFactory.newInstance().newXPath().compile("//" + elementName); 
     Node node = (Node) expr.evaluate(root, XPathConstants.NODE); 

     if (node != null) { 
      return getXPath(node); 
     } 
    } catch (XPathExpressionException e) { 
    } 

    return null; 
} 

public String getXPath(Node node) { 
    if (node == null || node.getNodeType() != Node.ELEMENT_NODE) { 
     return ""; 
    } 
    return getXPath(node.getParentNode()) + "/" + node.getNodeName(); 
} 

지금까지 데 문제가 반환 가져옵니다 [x] 그래서 XPath를 넣어하지 않습니다 getXPath 방법은 문자열 때문에 잘못이다 특정 태그의 인스턴스에있을 수 있는데이 경우 XPath는 같은 경로를 가진 모든 노드에 적용됩니다. 하나의 특정 요소 만 참조 할 수있는 정확한 경로를 원합니다.

+0

이것은 작동하지 않습니다. 새로운 노드 안에 일시적으로 XML의 일부분을 삽입 한 다음 XPath를 얻으면 인덱스 ('[x]')는 다른 경우와 다를 수 있습니다. 어쩌면 우리에게 ** 당신의 궁극적 인 목적이 무엇인지, 그리고 왜 당신이 이것을하고 있는지, 누군가 당신에게 그것을 어떻게하는지 알려줄 수 있습니다. – JLRishe

+0

좋아,이 XML'을'이 있고 주위 임시 노드를 있도록, 두 번째'gc'의 경로를 원하고'을 얻을 가정 '. 이제'/ root/child/temp' 인'temp'의 경로를 얻습니다. 이 경로에서'/ temp'를 제거하여'/ root/child'를 얻습니다. 이것은 두 번째'gc'의 경로를 얻지 못했습니다. – JLRishe

+1

이유를 설명하고 싶지 않은 이유가 있습니까? – JLRishe

답변

2

좋아는 (ideone example으로)이 방법은 다음과 같습니다

난 그냥 indexstartIndexendIndex을 변경했습니다. 임시 노드는 텍스트의 단일 지점에 추가 될 수 있습니다.

public static String findXPathInXMLString(int index, String string) throws XPathExpressionException, SAXException, ParserConfigurationException, IOException { 
    String xpath; 

    //Step 1. Insert temporary tag in insert location 
    StringBuilder stringBuilder = new StringBuilder(string); 
    stringBuilder.insert(index, "<findXPathInXMLStringTemporaryTag />"); 

    Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
     new ByteArrayInputStream(stringBuilder.toString().getBytes()) 
    ); 

    //Step 2. Convert string document to DOM document & Find XPath of temporary tag in DOM document 
    xpath = getXPath(document, "findXPathInXMLStringTemporaryTag"); 

    //Step 3. Cut off last part of the XPath 
    xpath = xpath.replace("/findXPathInXMLStringTemporaryTag", ""); 

    //Step 4. Return the XPath 
    return xpath; 
} 

private static String getXPath(Document root, String elementName) throws XPathExpressionException 
{ 
    XPathExpression expr = XPathFactory.newInstance().newXPath().compile("//"+elementName); 
    Node node = (Node)expr.evaluate(root, XPathConstants.NODE); 


    if(node != null) { 
     return getXPath(node); 
    } 

    return null; 
} 

private static String getXPath(Node node) throws XPathExpressionException { 
    if(node == null || node.getNodeType() != Node.ELEMENT_NODE) { 
     return ""; 
    } 

    return getXPath(node.getParentNode()) + "/" + node.getNodeName() + getIndex(node); 
} 

private static String getIndex(Node node) throws XPathExpressionException { 
    XPathExpression expr = XPathFactory.newInstance().newXPath().compile("count(preceding-sibling::*[local-name() = '" + node.getNodeName() + "'])"); 
    int result = (int)(double)(Double)expr.evaluate(node, XPathConstants.NUMBER); 

    if(result == 0){ 
     return ""; 
    } 
    else { 
     return "[" + (result + 1) + "]"; 
    } 
} 
+0

훌륭하고, 아주 좋습니다. 고맙습니다. 지금까지 해본 모든 테스트에서 효과가있었습니다. – ThreaT

관련 문제