2012-03-06 3 views
1

자바에서 정규식을 사용하여 xml을 변경하려고하는데 올바른 방법을 찾을 수 없습니다.자바에서 regexp를 사용하여 xml 수정하기

<ROOT> 
    <NODE ord="1" /> 
    <NODE ord="3,2" /> 
</ROOT> 

는 XML 실제로 두 언어에서의 노드, 청크와 문장을 ... 보여 더 많은 속성이 있습니다 :이 같은 XML (간체)가 있습니다. 각각의 문장은 두 개의 RichTextAreas에로드됩니다 (소스 문장에 대해 하나, 번역 된 문장에 대해 하나).

내가해야할 일은 ord 속성에 특정 값을 가진 모든 노드에 스타일 속성을 추가하는 것입니다.이 스타일 속성은 단어 위에 마우스를 가져 가면 Google 번역과 같은 두 언어 간의 일치를 나타냅니다. 나는 이것이 모든 노드 노드를 얻은 다음 ord 속성을 하나씩 보면서 DOM을 사용하여 수행 할 수 있음을 알고 있지만 GWT의 클라이언트 측에서 실행되도록 변경을 수행하는 가장 빠른 방법을 찾고있다. 앱.

ord 속성이 첫 번째 노드와 같은 단일 값을 갖는 경우 xml을 문자열로 가져오고 replaceAll() 함수를 사용하면됩니다. 문제는 속성이 두 번째 노드와 같이 값을 구성한 경우입니다.

예를 들어 내가 찾고있는 값이 2 인 경우 어떻게 그 속성을 추가 할 수 있습니까? 이 정규 표현식을 사용하여 수행 할 수 있다고 생각하지만 어떻게 찾을 수 없습니다. 어떤 힌트 나 도움을 주시면 감사하겠습니다 (regexp와 replaceAll 함수를 사용하지 않더라도).

미리 감사드립니다.

+3

XML을 정규식으로 구문 분석하지 마십시오. regex 권리를 얻는 데 문제가 있다면, 그렇게 두 배로하십시오. – Tomalak

+0

@Tomalak은 100 % 정확합니다. 여기서 정규 표현식을 사용하려고 시도하는 것은 잘못된 것입니다. –

+0

나는 이것이 가장 옳은 일이 아니라는 것을 알고있다. 그러나 사용자가 단어를 클릭 할 때마다이 작업을 수행해야하며, 이런 일이 발생할 때마다 구문 분석을하면 효과적이지 않을 것이라고 생각한다. – Ion

답변

1

XPath에 당신을 위해이 작업을 수행 할 수 있습니다. 당신은 선택할 수 있습니다 : 클라이언트에 GWT를 사용하려는 때문에, 당신은 gwtxslt 시도를 줄 수

/ROOT/NODE[contains(concat(',', @ord, ','), ',2,')] 

. XSLT 스타일 시트를 사용하여 변형을 수행 할 수 있습니다 (예 :당신을 위해 속성)를 추가하면 :

XsltProcessor processor = new XsltProcessor(); 
processor.importStyleSheet(styleSheetText); 
processor.importSource(sourceText); 
processor.setParameter("ord", "2"); 
processor.setParameter("style", "whatever"); 
String resultString = processor.transform(); 
// do something with resultString 

styleSheetText 내가 쉼표로 구분 된 목록에서 부분 일치를 방지하기 위해 concat()를 사용

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:param name="ord" select="''" /> 
    <xsl:param name="style" select="''" /> 

    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="NODE"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*" /> 
     <xsl:if test="contains(concat(',', @ord, ','), concat(',', $ord, ','))"> 
     <xsl:attribute name="style"> 
      <xsl:value-of select="$style" /> 
     </xsl:attribute> 
     </xsl:if> 
     <xsl:apply-templates select="node()" /> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

주의 선 속성을 따라 XSLT 문서를 할 수있는 곳 값은 @ord입니다.

+0

xpath를 사용하여 속성을 추가 할 수 있습니까? 나는 클라이언트 측면에서 totoe를 사용하고 있습니다. – Ion

+0

@ion No. XPath는 순수한 쿼리 언어이므로 올바른 노드를 선택하기 만하면됩니다. 노드를 한 가지 방법으로 처리해야합니다. XSLT는이를 수행하는 방법 중 하나입니다. DOM은 다른 방법 일 것입니다. – Tomalak

+0

Xpath는 정규식과 같습니다. 정규식은 텍스트의 비트 만 선택할 수 있습니다. 이들을 수정하려면 정규 표현식을 호스트하고 문자열을 수정할 수있는 프로그래밍 언어가 필요합니다. 여기서 XPath를 호스팅하고 XML 문서를 수정할 수있는 환경이 필요합니다. – Tomalak

0

과도한 소리처럼 들리 겠지만 표준 DOM 파서를 사용하여 조각을 읽고 setAttribute() 호출을 사용하여 수정 한 다음 다시 작성하는 방법을 고려해 보겠습니다. 당신이 효율성은 중요하다고 말한 것을 압니다. 그러나 이것이 실제로 얼마나 걸리나요? 테스트 결과, 내 노화 2GHz 펜티엄에서 60ms가 나타납니다.

이 접근법은 주석에 대해 더 강력 할 것이고, 선들 사이에서 분리되는 것들에 대해서 더 강력 할 것이다. 또한 당신에게 잘 구성된 XML을 줄 가능성이 훨씬 더 높다. 또한 특정 값이 존재하는 경우에만이를 수행한다는 요구 사항은 사소한 것이됩니다.

public class AddStyleExample { 

    public static void main(final String[] args) { 
     String input = "<ROOT> <NODE ord=\"1\" /> <NODE ord=\"3,2\" /> </ROOT>"; 
     try { 
      final DocumentBuilderFactory factory = DocumentBuilderFactory 
        .newInstance(); 
      factory.setValidating(false); 
      factory.setNamespaceAware(false); 
      DocumentBuilder builder; 

      builder = factory.newDocumentBuilder(); 

      final Document doc = builder.parse(new InputSource(
        new StringReader(input))); 

      NodeList tags = doc.getElementsByTagName("NODE"); 
      for (int i = 0; i < tags.getLength(); i++) { 
       Element node = (Element) tags.item(i); 
       node.setAttribute("style", "example value"); 
      } 
      StringWriter writer = new StringWriter(); 
      final StreamResult result = new StreamResult(writer); 
      final Transformer t = TransformerFactory.newInstance() 
        .newTransformer(); 
      t.setOutputProperty(OutputKeys.INDENT, "yes"); 
      t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
      t.transform(new DOMSource(doc), result); 
      System.out.println(writer.toString()); 

     } catch (ParserConfigurationException e) { 
      e.printStackTrace(); 
     } catch (TransformerException e) { 
      e.printStackTrace(); 
     } catch (SAXException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    } 
} 
+0

이것은 GWT 클라이언트 측에서 작동하지 않습니다! –

+0

OK가 허용되었지만 속도 때문에 DOM 파싱이 아닌 정규식을 원한다고 말했고, 지원되지 않았기 때문이 아닙니다. – Adam

+0

나는 아무것도 원하지 않는다 ;-) –

1
String resultString = subjectString.replaceAll("<NODE ord=\"([^\"]*\\b2\\b[^\"]*)\" />", "<NODE ord=\"$1\" style=\"whatever\"/>"); 

는 "2"(또는 "1,2"또는 "2,3"또는 "1,2,3"의 값을 갖는 단일 ord 특성을 갖는 임의 <NODE> 태그를 발견되지만 "12"가 아님) style 속성을 추가합니다.

이며, 많은 사람들이 불리하게 권고하고 있지만 일회성 일자리가 있으면 괜찮을 것입니다.

설명 :

<NODE ord=" # Match <NODE ord:" verbatim 
(   # Match and capture... 
[^"]*  # any number of characters except " 
\b2\b  # "2" as a whole word (surrounded by non-alphanumerics) 
[^"]*  # any number of characters except " 
)   # End of capturing group 
" />   # Match " /> verbatim 
+0

당신의 솔루션을 시도했지만 작동하지 않았습니다. 어쨌든 감사합니다. – Ion

+0

@Ion : 정확히 작동하지 않은 것은 무엇입니까? 자세한 내용은 제발. 정규 표현식의 문제점은 그들이 매우 용서하지 않는다는 것입니다. 규칙을 정확하게 정의해야합니다. 대소 문자, 공백, 모든 것이 중요합니다. –

+0

... 파서가 왜 항상 XML을 처리하는 것이 더 좋은지를 나타내는 지표이기도합니다. 왜냐하면이 모든 것이 투명하게 처리되기 때문입니다. (물론, 파서 자체가이를 수행하기 위해 정규 표현식을 사용하기 때문에 정확히 할 필요가 없습니다.) –

1

java에서 정규식을 사용하여 XML을 변경하려고하지만 올바른 방법을 찾을 수 없습니다.

올바른 방법이 없기 때문입니다. 정규 표현식은 XML을 조작하는 올바른 방법이 아닙니다. 왜냐하면 XML은 규칙적인 문법이 아니기 때문입니다. (일반화 된 모욕이 아니라 컴퓨터 과학의 전문 용어입니다.)

+0

xml을 간단한 문자열로 사용하는 대신 XML로 작업하는 것이 더 낫다는 것을 알고 있지만 DOM 접근법이 매우 비싸다고 생각합니다. – Ion

관련 문제