동기 부여:
회사 구조도를 만들어야 해서 처음 이진트리를 만들 생각을 하게 됐어요. 이전 접근방식은 그래픽 소프트웨어를 이용해 직접 그림을 그리는 방식이었다. 보기에는 좋지만 변경 사항이 있을 때마다 새로 칠해야 합니다. 반면 웹페이지의 줄 표시 및 레이아웃은 상당히 제한적입니다. 동적으로 생성된 데이터를 기반으로 한 조판 및 위치 지정은 매우 어렵고 미학적 측면도 만족스럽지 않습니다. 다양한 시도 끝에 데이터 작업에는 XML+XSL을 사용하고, 선을 아름답게 하려면 VML을 사용하고, 개체 위치를 지정하려면 JAVASCRIPT를 사용하기로 결정했습니다.
재료:
XML 볼륨의 구조 트리 다이어그램에는 flow2.xml 및 flow2.xsl이라는 두 개의 파일이 있습니다.
효과:
여기에서 찾아보세요
설명하다:
이진 트리 아이디어(1)
<html xmlns:v="urn:schemas-microsoft-com:vml">
<스타일>
v:* { 동작: url(#default#VML) }
</STYLE>
<v:group id="group1" name="group1" coordsize = "100,100">
…
</v:그룹>
VML의 기본 형식이므로 자세히 설명하지 않겠습니다.
XML은 트리 구조입니다. 각 데이터를 읽을 때 다음을 수행해야 합니다.
XML 데이터 트리가 탐색됩니다. 재귀 작업은 XSL의 장점 중 하나입니다.
또한 순회 작업을 수행하기 위해 다양한 다른 방법을 사용한 후 XSL을 사용하기로 결정했지만 실패했습니다.
<플로우루트>
<vcTitle>이진 트리-구조 다이어그램</vcTitle>
<저자>항해</저자>
<Email>[email protected]</Email>
<플로우노드>
<iProcess>1</iProcess>
<vcCourse>첫 번째 노드</vcCourse>
<i다음예>
<플로우노드>
<iProcess>2</iProcess>
<vcCourse>두 번째 노드</vcCourse>
<iNext예>…</iNext예>
<iNextNo>…</iNextNo>
</FlowNode>
</i다음예>
<i다음아니요>
<플로우노드>
<iProcess>3</iProcess>
<vcCourse>세 번째 노드</vcCourse>
<iNext예>…</iNext예>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextNo>
</FlowNode>
</FlowRoot>
논리는 매우 간단합니다. 현재 노드(1) 아래에 두 개의 하위 노드(2, 3)가 있습니다.
노드 1의 왼쪽 하단과 오른쪽 하단에 노드 2와 노드 3을 배치하면 됩니다.
여기서는 쉽게 표시하기 위해 왼쪽 노드와 오른쪽 노드의 연결선에 각각 녹색과 빨간색을 사용했습니다.
앞서 XSL의 재귀 기능에 대해 설명했습니다. 각 세부 표시 단계를 더 명확하게 보려면 다음 코드를 모방하고 경고 문을 추가하기만 하면 됩니다.
<xsl:템플릿 일치="FlowNode">
…
<SCRIPT 언어="JavaScript1.2">
…
Alert('단계별로 표시');
…
</SCRIPT>
…
</xsl:템플릿>
위의 슬로우모션을 보시면 제 생각이 이해가 되시나요?
이진 트리 아이디어(2)
내 생각은 매우 간단합니다.
(1) 현재 노드의 데이터를 읽고 VML을 이용하여 새로운 객체를 생성한다.
개체에 초기 값(예: 이름, ID, 스타일 등)을 할당합니다.
(2) 스크립트 컨트롤을 사용하여 현재 개체의 위치를 지정합니다. (3) 현재 노드와 상위 노드 사이에 화살표와 선을 추가합니다.
(4) 계속해서 현재 노드의 자식 노드를 찾아 끝까지 반복합니다.
즉, 모든 노드를 순회하여 트리가 생성되었습니다.
<xsl:템플릿 일치="FlowNode">
…
<xsl:적용-템플릿 />
…
</xsl:템플릿>
<xsl:템플릿 일치="iNextYes">
<xsl:apply-templates select="./FlowNode" />
</xsl:template>
<xsl:template match="iNextNo">
<xsl:apply-templates select="./FlowNode" />
</xsl:템플릿>
전체 재귀 프로세스는 위의 세 가지 모듈(템플릿)에 의해 완료됩니다.
첫 번째 템플릿은 현재 노드의 각 하위 노드의 템플릿을 일치시킬 때 다음 두 템플릿을 호출하고, 후자 두 템플릿은 특정 실행 중에 첫 번째 템플릿을 호출하며 이는 재귀 함수와 동일합니다.
문법:
현재 노드에 있는 각 하위 노드의 템플릿을 차례로 일치시키려면 요소의 기본 형식 <xsl:apply-templates />를 사용합니다.
그렇지 않은 경우 일치하는 노드는 <xsl:apply-templates select="./FlowNode" />와 같은 select 매개변수의 XPath 표현식 값에 의해 결정됩니다.
(1)과 (2)의 기능은 select 매개변수에 의해 제공된 표현식의 문자열 값을 반환하는 것입니다.
검색 조건이 동일하므로 반환되는 값도 동일합니다.
단지 사용되는 경우에 따라 글쓰기 형식이 다를 뿐입니다.
(1) <xsl:value-of select="./iProcess/text()" />
(2) {./iProcess/text()}
여기에는 일부 변수가 정의되어 있으며, 노드의 위치는 이러한 변수를 기반으로 계산 공식을 호출합니다.
root_left //루트의 왼쪽 마진 = 모든 리프의 할당 너비(y*10) + 모든 리프의 너비(y*50) + 왼쪽 마진의 기본 값(10)
root_top //루트의 상단 여백 = 상단 여백의 기본 값(10)
objOval //현재 객체가 객체입니다.
objOval_iProcess //현재 객체의 단계 값
objParentOval //현재 객체의 부모 노드는 객체입니다.
objParentOval_iProcess //현재 객체의 부모 노드의 단계 값
objParent_name //현재 객체의 부모 노드 이름
Leaf_left //현재 객체의 모든 자식 노드 중 왼쪽 리프 수
Leaf_right //현재 객체의 모든 자식 노드 중 오른쪽 리프 수
Leaf_sum //현재 객체의 모든 자식 노드 중 리프 수입니다.
리프: 자식 노드가 없는 현재 노드를 나타냅니다.
노드 위치 지정 공식:
(1) 현재 노드는 루트 노드입니다.
//루트의 위치
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
//parseInt() 함수의 함수는 정수 값을 취하는 것입니다. 그렇지 않으면 NAN이 됩니다.
//isNaN() 함수의 함수는parseInt에서 얻은 값이 정수인지 여부를 확인하는 것입니다.
(2) 현재 노드는 부모 노드의 왼쪽 자식 노드입니다.
1) 판단 조건은 현재 객체의 부모 노드 이름 = 'iNextYes'
…
2) 오른쪽 자식 리프가 있는 경우 공식은 다음과 같습니다.
현재 노드의 왼쪽 = 부모 노드의 왼쪽 - 현재 노드의 오른쪽 자식 리프의 전체 너비 - 현재 노드의 너비
3) 오른쪽 자식 리프는 없고 왼쪽 자식 리프가 있는 경우 , 공식은 다음과 같습니다.
현재 노드의 왼쪽 = 부모 노드의 왼쪽 - 현재 노드의 왼쪽 자식 리프의 전체 너비
4) 현재 노드 자체가 리프인 경우 수식은 다음과 같습니다.
현재 노드의 왼쪽 = 부모 노드의 왼쪽 - 현재 노드의 너비...
(3) 현재 노드는 부모 노드의 오른쪽 자식 노드입니다.
1) 판단 조건은 현재 객체의 부모 노드 이름 = 'iNextNo'
…
2) 왼쪽 자식 리프가 있는 경우 공식은 다음과 같습니다.
현재 노드의 왼쪽 = 부모 노드의 왼쪽 + 현재 노드의 왼쪽 자식 리프의 전체 너비 + 현재 노드의 너비
3) 왼쪽 자식 리프는 없고 오른쪽 자식 리프가 있는 경우 , 공식은 다음과 같습니다.
현재 노드의 왼쪽 = 부모 노드의 왼쪽 + 현재 노드의 오른쪽 자식 리프의 총 너비
4) 현재 노드 자체가 리프인 경우 수식은 다음과 같습니다.
현재 노드의 왼쪽 = 부모 노드의 왼쪽 + 현재 노드의 너비...
수식 (2)와 (3)은 모두 현재 노드의 왼쪽을 가져오며, 현재 노드의 맨 위도 가져와야 합니다.
매우 간단한 공식: 현재 노드의 상단 = 상위 노드의 상단 + 오프셋(80)
이진 트리 아이디어(3)
선 연결을 위한 위치 지정 아이디어:
(1) 현재 노드와 부모 노드의 위치를 구합니다. (2) 현재 노드가 부모 노드의 왼쪽 자식 노드인지 오른쪽 자식 노드인지 확인합니다. (3) 선을 그립니다.
여기에는 일부 변수가 정의되어 있습니다.
objOval //현재 노드는 객체입니다.
objParentOval //현재 객체의 부모 노드는 객체입니다.
objLine //현재 라인은 객체입니다.
라인 포지셔닝 공식:
from="x1,y1" to="x2,y2" 는 VML에서 줄을 배치하는 방법입니다.
현재 노드는 상위 노드의 왼쪽 하위 노드이며 공식은 다음과 같습니다.
from = 부모 노드의 왼쪽 + 오프셋(15), 부모 노드의 위쪽 + 오프셋(32)
to = 왼쪽 + 부모 노드의 오프셋(30), 위쪽 - 부모 노드의 오프셋(2)
현재 노드는 부모 노드의 오른쪽 자식 노드이며 공식은 다음과 같습니다.
from = 상위 노드 왼쪽 + 오프셋(35), 상위 노드 상단 + 오프셋(32)
to = 상위 노드 왼쪽 + 오프셋(20), 상위 노드 상단 - 오프셋(2)
그게 내가 생각할 수 있는 전부야.
회사 구조도만 만들어 놓으면 훨씬 간단해집니다.
다음은 사이영의 생각인데, 그를 토대로 좀 더 깊이 들어가 보겠습니다.
먼저 최하위 레벨의 노드 수를 계산하여 너비를 구하고,
그런 다음 노드의 상위 노드 위치는 해당 소속을 기반으로 재귀적으로 계산되어야 합니다.
각 수준의 노드는 소속에 따라 정렬되어야 합니다. 먼저 "기본 값"을 설정합니다. 즉, 노드는 오른쪽으로 오프셋되어야 합니다. 자식 노드를 포함하는 각 노드의 왼쪽 값은 해당 노드 너비의 절반과 같습니다. 기본 가치를 더해 소유합니다.
추신:
최근 어떤 이유에서인지 인터넷 상태가 좋지 않습니다. 온라인보다 오프라인에서 더 많은 시간을 보내세요.
따라서 코드가 단순화되지 않았습니다. 실제로 다음과 같이 개선해야 할 기능이 많이 있습니다.
오른쪽 클릭 메뉴를 추가해야 합니다. 오른쪽 클릭 메뉴에는 새 노드 생성, 노드 이름 수정, 연결 변경 등의 기능이 포함되어 있습니다. 각 노드를 마우스 오른쪽 버튼으로 클릭하면 이 노드의 오른쪽 클릭 메뉴를 열 수 있습니다. .
설명하다:
1) flow2.xml은 데이터 파일이므로 누구에게나 문제가 없을 것이라고 믿습니다.
2) flow2.xsl은 형식 파일이므로 주의할 점이 몇 가지 있습니다.
(1) 스크립트에서:
(1) <xsl:value-of select="./iProcess/text()" />;
(2) {./iProcess/text()}
(1)과 (2)의 함수는 select 매개변수에 의해 제공된 표현식의 문자열 값을 반환하는 것입니다.
검색 조건이 동일하므로 반환되는 값도 동일합니다.
단지 사용되는 경우에 따라 글쓰기 형식이 다를 뿐입니다.
<xsl:apply-templates select="팀" order-by="blue_ID"/>
예를 들어 다음 코드를 생성하려고 합니다.
<div name="parameter value">콘텐츠</div>
이름은 "name"이고 매개변수 값은 XML 데이터의 현재 노드 아래에 있는 하위 노드 책의 값이라고 가정합니다.
이를 작성하는 첫 번째 방법은 속성 이름을 먼저 추가한 다음 매개변수 값을 추가하는 것입니다.
<div>
<xsl:속성 이름="이름">
<xsl:value-of select="./book/text()"/> </xsl:attribute>
콘텐츠
</div>
두 번째 작성 방법은 속성 이름과 매개변수 값을 직접 추가하는 것입니다.
<div name="{./book/text()}">Content</div>
구체적인 사용법은 제가 작성한 코드의 예시를 참조하세요.
XSL은 공식 표준 xmlns:xsl=" http://www.w3.org/1999/XSL/Transform "
<xsl:value-of select="./book/text()"/>
에 있습니다.
기능은 다음과 같습니다. 텍스트 값을 작성하고
<xsl:value-of select="./book"/>
텍스트 값과 모든 하위 노드의 내용을 표시합니다.
이를 시험해보고 하위 노드가 있는 것과 하위 노드가 없는 것을 출력하여 표시된 결과가 동일한지 확인할 수 있습니다.
(2) 참고:
IE5는 <tag att="{xpath}">를 지원하지 않습니다.
사용하고 싶다
<tag><xsl:attribute name="att"><xsl:value-of select="xpath"></xsl:attribute>
네임스페이스를 사용해야 합니다.
xmlns:xsl=" http://www.w3.org/TR/WD-xsl "
<?xml 버전="1.0" 인코딩="gb2312" ?>
한 가지 더:
Encoding="gb2312"는 대부분의 XML 교과서에 표시된 코드에 거의 추가되지 않습니다.
따라서 XML에서 중국어를 사용하면 오류가 보고됩니다. 그 이유는 이 선언이 작성되지 않았기 때문입니다.
추신:
내가 여기서 말하는 것은 사고방식이다. 비유를 그리면 자연스럽게 도움이 될 것입니다.