문제

나는 서로에게 공급되는 일련의 XSL 2.0 스타일 시트가 있습니다. 즉, 스타일 시트의 출력 A 피드 B 피드 C.

이 작업을 수행하는 가장 효율적인 방법은 무엇입니까? 다시 판결 된 질문은 다음과 같습니다. 하나의 변환의 출력을 다른 변환의 출력을 어떻게 효율적으로 라우팅 할 수 있습니까?

첫 번째 시도는 다음과 같습니다.

@Override
public void transform(Source data, Result out) throws TransformerException{
    for(Transformer autobot : autobots){
        if(autobots.indexOf(autobot) != (autobots.size()-1)){
            log.debug("Transforming prelim stylesheet...");
            data = transform(autobot,data);
        }else{
            log.debug("Transforming final stylesheet...");
            autobot.transform(data, out);
        }
    }
}

private Source transform(Transformer autobot, Source data) throws TransformerException{
    DOMResult result = new DOMResult();
    autobot.transform(data, result);
    Node node = result.getNode();
    return new DOMSource(node);
}

보시다시피, 나는 DOM을 사용하여 변형 사이에 앉아 있고 편리하지만 최적의 성능이 현명합니다.

Saxresult를 색소폰으로 라우팅 할 수있는 쉬운 방법이 있습니까? Stax 솔루션은 또 다른 옵션입니다.

나는 같은 프로젝트를 알고 있습니다 xproc, 당신이 아직 보지 않았다면 매우 멋지다. 그러나 나는 전체 프레임 워크에 투자하고 싶지 않았다.

도움이 되었습니까?

해결책

나는 이것을 찾았다: #삼. 체인 변환 두 가지 사용 방법을 보여줍니다 변압력 변환을 체인하여 하나의 변환 결과를 갖는 다음 변환을 피드 한 다음 마지막으로 시스템을 출력합니다. 이것은 변환 사이의 문자열, 파일 등에 대한 중간 직렬화가 필요하지 않습니다.

동일한 XML 문서에 여러 번의 연속적인 변환이 필요한 경우 불필요한 구문 분석 작업을 피하십시오. 나는 종종 문자열을 다른 문자열로 변환하는 코드를 사용한 다음 해당 문자열을 다른 문자열로 변환합니다. 이것은 느리게뿐만 아니라 특히 중간 줄을 수집 할 수없는 경우 상당한 양의 기억을 소비 할 수 있습니다.

대부분의 변환은 일련의 색소폰 이벤트를 기반으로합니다. 색소폰 파서는 일반적으로 입력 스트림 또는 다른 입력 소스를 SAX 이벤트에 구문 분석 한 다음 변압기에 공급 될 수 있습니다. 파일, 문자열 또는 다른 결과에 변압기 출력을하는 대신 saxresult를 대신 사용할 수 있습니다. Saxresult는 Contenthandler를 수락하여 이러한 색소폰 이벤트를 다른 변압기 등으로 직접 전달할 수 있습니다.

여기에 하나의 접근법이 있으며, 다양한 입력 및 출력 소스에 대한 유연성을 제공하기 때문에 일반적으로 선호하는 방법. 또한 변환 체인을 동적으로 그리고 가변적 인 수의 변환으로 쉽게 만들 수 있습니다.

SAXTransformerFactory stf = (SAXTransformerFactory)TransformerFactory.newInstance();

// These templates objects could be reused and obtained from elsewhere.
Templates templates1 = stf.newTemplates(new StreamSource(
  getClass().getResourceAsStream("MyStylesheet1.xslt")));
Templates templates2 = stf.newTemplates(new StreamSource(
  getClass().getResourceAsStream("MyStylesheet1.xslt")));

TransformerHandler th1 = stf.newTransformerHandler(templates1);
TransformerHandler th2 = stf.newTransformerHandler(templates2);

th1.setResult(new SAXResult(th2));
th2.setResult(new StreamResult(System.out));

Transformer t = stf.newTransformer();
t.transform(new StreamSource(System.in), new SAXResult(th1));

// th1 feeds th2, which in turn feeds System.out.

다른 팁

가장 좋은 방법은 XSLT 프로세서가 트리를 만들어야하기 때문에 DOM을 고수하는 것입니다. 스트리밍은 매우 제한된 범주의 변환을위한 옵션 일 뿐이며 프로세서가 자동으로 파악하고 전환 할 수있는 경우에는 거의 없습니다. 스트리밍 전용 구현으로; 그렇지 않으면 그들은 입력을 읽고 나무를 만듭니다.

관련 질문 Java의 Params와 함께 효율적인 XSLT 파이프 라인 이러한 변압기 체인으로 전달되는 올바른 파라미터에 대해 설명합니다.

또한 세 번째 변압기없이 약간 짧은 솔루션에 대한 힌트를주었습니다.

SAXTransformerFactory stf = (SAXTransformerFactory)TransformerFactory.newInstance();

Templates templates1 = stf.newTemplates(new StreamSource(
        getClass().getResourceAsStream("MyStylesheet1.xslt")));
Templates templates2 = stf.newTemplates(new StreamSource(
        getClass().getResourceAsStream("MyStylesheet2.xslt")));

TransformerHandler th1 = stf.newTransformerHandler(templates1);
TransformerHandler th2 = stf.newTransformerHandler(templates2);

th2.setResult(new StreamResult(System.out));

// Note that indent, etc should be applied to the last transformer in chain:
th2.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");

th1.getTransformer().transform(new StreamSource(System.in), new SAXResult(th2));
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top