|
|
|
|
@@ -50,7 +50,14 @@ public class WmtsService {
|
|
|
|
|
return getLayerInfoByTitle(geoserverUrl, workspace, tile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<WmtsLayerInfo> getAllLayers(String geoserverUrl, String workspace) {
|
|
|
|
|
/**
|
|
|
|
|
* WMTS Capabilities URL에서 모든 레이어 정보를 가져옵니다.
|
|
|
|
|
*
|
|
|
|
|
* @param geoserverUrl 예: http://localhost:8080
|
|
|
|
|
* @param workspace 워크스페이스 이름
|
|
|
|
|
* @return 모든 레이어 정보 리스트
|
|
|
|
|
*/
|
|
|
|
|
public List<WmtsLayerInfo> getAllLayers(String geoserverUrl, String workspace) {
|
|
|
|
|
List<WmtsLayerInfo> layers = new ArrayList<>();
|
|
|
|
|
try {
|
|
|
|
|
// 1. XML 문서 로드 및 파싱
|
|
|
|
|
@@ -75,7 +82,7 @@ public class WmtsService {
|
|
|
|
|
String title = getChildValue(layerNode, "Title");
|
|
|
|
|
|
|
|
|
|
if (title != null && !title.trim().isEmpty()) {
|
|
|
|
|
WmtsLayerInfo layerInfo = parseLayerNode(layerNode, title);
|
|
|
|
|
WmtsLayerInfo layerInfo = parseLayerNode(workspace, layerNode, title);
|
|
|
|
|
layers.add(layerInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -88,151 +95,6 @@ public class WmtsService {
|
|
|
|
|
return layers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 특정 노드 아래의 자식 태그 값 추출 (예: <Title>값)
|
|
|
|
|
private String getChildValue(Node parent, String childName) {
|
|
|
|
|
Node child = findChildNode(parent, childName);
|
|
|
|
|
return (child != null) ? child.getTextContent() : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 이름으로 자식 노드 찾기 (Local Name 기준)
|
|
|
|
|
private Node findChildNode(Node parent, String localName) {
|
|
|
|
|
NodeList children = parent.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
// 네임스페이스 접두사(ows:, wmts:)를 무시하고 태그 이름 확인
|
|
|
|
|
if (node.getNodeName().endsWith(":" + localName) || node.getNodeName().equals(localName)) {
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 레이어 노드를 Java 객체로 변환
|
|
|
|
|
private WmtsLayerInfo parseLayerNode(Node layerNode, String title) {
|
|
|
|
|
WmtsLayerInfo info = new WmtsLayerInfo();
|
|
|
|
|
info.title = title;
|
|
|
|
|
info.identifier = getChildValue(layerNode, "Identifier");
|
|
|
|
|
info.abstractText = getChildValue(layerNode, "Abstract");
|
|
|
|
|
|
|
|
|
|
// Keywords 파싱
|
|
|
|
|
// 구조: <ows:Keywords><ows:Keyword>...</ows:Keyword></ows:Keywords>
|
|
|
|
|
info.keywords = getChildValues(layerNode, "Keywords", "Keyword");
|
|
|
|
|
|
|
|
|
|
// BoundingBox 파싱 (WGS84BoundingBox 기준)
|
|
|
|
|
info.boundingBox = parseBoundingBox(layerNode);
|
|
|
|
|
|
|
|
|
|
// Formats 파싱
|
|
|
|
|
info.formats = getChildValuesDirect(layerNode, "Format");
|
|
|
|
|
|
|
|
|
|
// TileMatrixSetLink 파싱
|
|
|
|
|
// 구조: <TileMatrixSetLink><TileMatrixSet>...</TileMatrixSet></TileMatrixSetLink>
|
|
|
|
|
info.tileMatrixSetLinks = getChildValues(layerNode, "TileMatrixSetLink", "TileMatrixSet");
|
|
|
|
|
|
|
|
|
|
// ResourceURL 파싱
|
|
|
|
|
info.resourceUrls = parseResourceUrls(layerNode);
|
|
|
|
|
|
|
|
|
|
// Styles 파싱
|
|
|
|
|
info.styles = parseStyles(layerNode);
|
|
|
|
|
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 특정 노드 아래의 반복되는 자식 구조 값 추출 (예: Keywords -> Keyword)
|
|
|
|
|
private List<String> getChildValues(Node parent, String wrapperName, String childName) {
|
|
|
|
|
List<String> results = new ArrayList<>();
|
|
|
|
|
Node wrapper = findChildNode(parent, wrapperName);
|
|
|
|
|
if (wrapper != null) {
|
|
|
|
|
NodeList children = wrapper.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().endsWith(childName)) {
|
|
|
|
|
results.add(node.getTextContent());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private WmtsLayerInfo.BoundingBox parseBoundingBox(Node layerNode) {
|
|
|
|
|
// 보통 <ows:WGS84BoundingBox>를 찾음
|
|
|
|
|
Node bboxNode = findChildNode(layerNode, "WGS84BoundingBox");
|
|
|
|
|
if (bboxNode == null) bboxNode = findChildNode(layerNode, "BoundingBox");
|
|
|
|
|
|
|
|
|
|
if (bboxNode != null) {
|
|
|
|
|
WmtsLayerInfo.BoundingBox bbox = new WmtsLayerInfo.BoundingBox();
|
|
|
|
|
bbox.crs = getAttributeValue(bboxNode, "crs"); // WGS84는 보통 CRS 속성이 없을 수 있음(Default EPSG:4326)
|
|
|
|
|
|
|
|
|
|
String lowerCorner = getChildValue(bboxNode, "LowerCorner");
|
|
|
|
|
String upperCorner = getChildValue(bboxNode, "UpperCorner");
|
|
|
|
|
|
|
|
|
|
if (lowerCorner != null) {
|
|
|
|
|
String[] coords = lowerCorner.split(" ");
|
|
|
|
|
bbox.lowerCornerX = Double.parseDouble(coords[0]);
|
|
|
|
|
bbox.lowerCornerY = Double.parseDouble(coords[1]);
|
|
|
|
|
}
|
|
|
|
|
if (upperCorner != null) {
|
|
|
|
|
String[] coords = upperCorner.split(" ");
|
|
|
|
|
bbox.upperCornerX = Double.parseDouble(coords[0]);
|
|
|
|
|
bbox.upperCornerY = Double.parseDouble(coords[1]);
|
|
|
|
|
}
|
|
|
|
|
return bbox;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getAttributeValue(Node node, String attrName) {
|
|
|
|
|
if (node.hasAttributes()) {
|
|
|
|
|
Node attr = node.getAttributes().getNamedItem(attrName);
|
|
|
|
|
if (attr != null) return attr.getNodeValue();
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wrapper 없이 바로 반복되는 값 추출 (예: Format)
|
|
|
|
|
private List<String> getChildValuesDirect(Node parent, String childName) {
|
|
|
|
|
List<String> results = new ArrayList<>();
|
|
|
|
|
NodeList children = parent.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().endsWith(childName)) {
|
|
|
|
|
results.add(node.getTextContent());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<WmtsLayerInfo.ResourceUrl> parseResourceUrls(Node layerNode) {
|
|
|
|
|
List<WmtsLayerInfo.ResourceUrl> list = new ArrayList<>();
|
|
|
|
|
NodeList children = layerNode.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().contains("ResourceURL")) { // local-name check simplification
|
|
|
|
|
WmtsLayerInfo.ResourceUrl url = new WmtsLayerInfo.ResourceUrl();
|
|
|
|
|
url.setFormat(getAttributeValue(node, "format"));
|
|
|
|
|
url.setResourceType(getAttributeValue(node, "resourceType"));
|
|
|
|
|
url.setTemplate(getAttributeValue(node, "template"));
|
|
|
|
|
list.add(url);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<WmtsLayerInfo.Style> parseStyles(Node layerNode) {
|
|
|
|
|
List<WmtsLayerInfo.Style> styles = new ArrayList<>();
|
|
|
|
|
NodeList children = layerNode.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().endsWith("Style")) {
|
|
|
|
|
WmtsLayerInfo.Style style = new WmtsLayerInfo.Style();
|
|
|
|
|
style.setDefault(Boolean.parseBoolean(getAttributeValue(node, "isDefault")));
|
|
|
|
|
style.setIdentifier(getChildValue(node, "Identifier"));
|
|
|
|
|
style.setTitle(getChildValue(node, "Title"));
|
|
|
|
|
styles.add(style);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return styles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WMTS Capabilities URL에서 특정 타이틀의 레이어 정보를 가져옵니다. // * @param capabilitiesUrl 예:
|
|
|
|
|
* http://localhost:8080/geoserver/gwc/service/wmts?REQUEST=GetCapabilities
|
|
|
|
|
@@ -268,7 +130,7 @@ public class WmtsService {
|
|
|
|
|
|
|
|
|
|
// 타이틀이 일치하면 객체 매핑 시작
|
|
|
|
|
if (title != null && title.trim().equals(targetTitle)) {
|
|
|
|
|
return parseLayerNode(layerNode, title);
|
|
|
|
|
return parseLayerNode(workspace, layerNode, title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -279,4 +141,249 @@ public class WmtsService {
|
|
|
|
|
|
|
|
|
|
return null; // 찾지 못한 경우
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 레이어 노드를 Java 객체로 변환 20250130
|
|
|
|
|
private WmtsLayerInfo parseLayerNode(String workspace, Node layerNode, String title) {
|
|
|
|
|
WmtsLayerInfo info = new WmtsLayerInfo();
|
|
|
|
|
info.workspace = workspace; // 20250130
|
|
|
|
|
info.title = title;
|
|
|
|
|
info.identifier = getChildValue(layerNode, "Identifier");
|
|
|
|
|
info.abstractText = getChildValue(layerNode, "Abstract");
|
|
|
|
|
|
|
|
|
|
// Keywords 파싱
|
|
|
|
|
// 구조: <ows:Keywords><ows:Keyword>...</ows:Keyword></ows:Keywords>
|
|
|
|
|
info.keywords = getChildValues(layerNode, "Keywords", "Keyword");
|
|
|
|
|
|
|
|
|
|
// BoundingBox 파싱 (WGS84BoundingBox 기준)
|
|
|
|
|
info.boundingBox = parseBoundingBox(layerNode);
|
|
|
|
|
|
|
|
|
|
// Formats 파싱
|
|
|
|
|
info.formats = getChildValuesDirect(layerNode, "Format");
|
|
|
|
|
|
|
|
|
|
// TileMatrixSetLink 파싱 (TileMatrixSet + Zoom Levels)
|
|
|
|
|
info.tileMatrixSetLinks = parseTileMatrixSetLinks(layerNode);
|
|
|
|
|
|
|
|
|
|
// TileMatrixSetLimits에서 줌 레벨 추출 (개별 zoom 리스트)
|
|
|
|
|
info.matrixIds = parseMatrixIds(layerNode); // 20260130
|
|
|
|
|
|
|
|
|
|
// ResourceURL 파싱
|
|
|
|
|
info.resourceUrls = parseResourceUrls(layerNode);
|
|
|
|
|
|
|
|
|
|
// Styles 파싱
|
|
|
|
|
info.styles = parseStyles(layerNode);
|
|
|
|
|
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- Helper Methods ---
|
|
|
|
|
|
|
|
|
|
private WmtsLayerInfo.BoundingBox parseBoundingBox(Node layerNode) {
|
|
|
|
|
// 보통 <ows:WGS84BoundingBox>를 찾음
|
|
|
|
|
Node bboxNode = findChildNode(layerNode, "WGS84BoundingBox");
|
|
|
|
|
if (bboxNode == null) bboxNode = findChildNode(layerNode, "BoundingBox");
|
|
|
|
|
|
|
|
|
|
if (bboxNode != null) {
|
|
|
|
|
WmtsLayerInfo.BoundingBox bbox = new WmtsLayerInfo.BoundingBox();
|
|
|
|
|
bbox.crs = getAttributeValue(bboxNode, "crs"); // WGS84는 보통 CRS 속성이 없을 수 있음(Default EPSG:4326)
|
|
|
|
|
|
|
|
|
|
String lowerCorner = getChildValue(bboxNode, "LowerCorner");
|
|
|
|
|
String upperCorner = getChildValue(bboxNode, "UpperCorner");
|
|
|
|
|
|
|
|
|
|
if (lowerCorner != null) {
|
|
|
|
|
String[] coords = lowerCorner.split(" ");
|
|
|
|
|
bbox.lowerCornerX = Double.parseDouble(coords[0]);
|
|
|
|
|
bbox.lowerCornerY = Double.parseDouble(coords[1]);
|
|
|
|
|
}
|
|
|
|
|
if (upperCorner != null) {
|
|
|
|
|
String[] coords = upperCorner.split(" ");
|
|
|
|
|
bbox.upperCornerX = Double.parseDouble(coords[0]);
|
|
|
|
|
bbox.upperCornerY = Double.parseDouble(coords[1]);
|
|
|
|
|
}
|
|
|
|
|
return bbox;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<WmtsLayerInfo.ResourceUrl> parseResourceUrls(Node layerNode) {
|
|
|
|
|
List<WmtsLayerInfo.ResourceUrl> list = new ArrayList<>();
|
|
|
|
|
NodeList children = layerNode.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().contains("ResourceURL")) { // local-name check simplification
|
|
|
|
|
WmtsLayerInfo.ResourceUrl url = new WmtsLayerInfo.ResourceUrl();
|
|
|
|
|
url.setFormat(getAttributeValue(node, "format"));
|
|
|
|
|
url.setResourceType(getAttributeValue(node, "resourceType"));
|
|
|
|
|
url.setTemplate(getAttributeValue(node, "template"));
|
|
|
|
|
list.add(url);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<WmtsLayerInfo.Style> parseStyles(Node layerNode) {
|
|
|
|
|
List<WmtsLayerInfo.Style> styles = new ArrayList<>();
|
|
|
|
|
NodeList children = layerNode.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().endsWith("Style")) {
|
|
|
|
|
WmtsLayerInfo.Style style = new WmtsLayerInfo.Style();
|
|
|
|
|
style.setDefault(Boolean.parseBoolean(getAttributeValue(node, "isDefault")));
|
|
|
|
|
style.setIdentifier(getChildValue(node, "Identifier"));
|
|
|
|
|
style.setTitle(getChildValue(node, "Title"));
|
|
|
|
|
styles.add(style);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return styles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* TileMatrixSetLimits에서 줌 레벨을 추출합니다. 예: "EPSG:4326:0" → "0", "EPSG:4326:1" → "1"
|
|
|
|
|
*
|
|
|
|
|
* @param layerNode Layer 노드
|
|
|
|
|
* @return 줌 레벨 문자열 리스트
|
|
|
|
|
*/
|
|
|
|
|
private List<String> parseMatrixIds(Node layerNode) {
|
|
|
|
|
List<String> matrixIds = new ArrayList<>();
|
|
|
|
|
NodeList children = layerNode.getChildNodes();
|
|
|
|
|
|
|
|
|
|
// 모든 TileMatrixSetLink 찾기
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().contains("TileMatrixSetLink")) {
|
|
|
|
|
// TileMatrixSetLimits 찾기
|
|
|
|
|
Node limitsNode = findChildNode(node, "TileMatrixSetLimits");
|
|
|
|
|
if (limitsNode != null) {
|
|
|
|
|
NodeList limitsList = limitsNode.getChildNodes();
|
|
|
|
|
// 각 TileMatrixLimits 처리
|
|
|
|
|
for (int j = 0; j < limitsList.getLength(); j++) {
|
|
|
|
|
Node limitNode = limitsList.item(j);
|
|
|
|
|
if (limitNode.getNodeName().contains("TileMatrixLimits")) {
|
|
|
|
|
// TileMatrix 또는 Identifier 값 추출
|
|
|
|
|
String identifier = getChildValue(limitNode, "TileMatrix");
|
|
|
|
|
if (identifier == null) {
|
|
|
|
|
identifier = getChildValue(limitNode, "Identifier");
|
|
|
|
|
}
|
|
|
|
|
// 마지막 콜론 이후 값(줌 레벨) 추출
|
|
|
|
|
if (identifier != null && identifier.contains(":")) {
|
|
|
|
|
String[] parts = identifier.split(":");
|
|
|
|
|
String zoomLevel = parts[parts.length - 1];
|
|
|
|
|
matrixIds.add(zoomLevel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return matrixIds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* TileMatrixSetLink 정보를 파싱합니다. 각 TileMatrixSetLink에서 TileMatrixSet 이름과 줌 레벨들을 추출합니다.
|
|
|
|
|
*
|
|
|
|
|
* @param layerNode Layer 노드
|
|
|
|
|
* @return TileMatrixSetLink 객체 리스트
|
|
|
|
|
*/
|
|
|
|
|
private List<WmtsLayerInfo.TileMatrixSetLink> parseTileMatrixSetLinks(Node layerNode) {
|
|
|
|
|
List<WmtsLayerInfo.TileMatrixSetLink> links = new ArrayList<>();
|
|
|
|
|
NodeList children = layerNode.getChildNodes();
|
|
|
|
|
|
|
|
|
|
// 모든 TileMatrixSetLink 찾기
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().contains("TileMatrixSetLink")) {
|
|
|
|
|
|
|
|
|
|
// TileMatrixSet 이름 추출
|
|
|
|
|
String tileMatrixSet = getChildValue(node, "TileMatrixSet");
|
|
|
|
|
|
|
|
|
|
// 줌 레벨들 추출
|
|
|
|
|
List<String> zoomLevels = new ArrayList<>();
|
|
|
|
|
Node limitsNode = findChildNode(node, "TileMatrixSetLimits");
|
|
|
|
|
if (limitsNode != null) {
|
|
|
|
|
NodeList limitsList = limitsNode.getChildNodes();
|
|
|
|
|
for (int j = 0; j < limitsList.getLength(); j++) {
|
|
|
|
|
Node limitNode = limitsList.item(j);
|
|
|
|
|
if (limitNode.getNodeName().contains("TileMatrixLimits")) {
|
|
|
|
|
// TileMatrix 또는 Identifier 값 추출
|
|
|
|
|
String identifier = getChildValue(limitNode, "TileMatrix");
|
|
|
|
|
if (identifier == null) {
|
|
|
|
|
identifier = getChildValue(limitNode, "Identifier");
|
|
|
|
|
}
|
|
|
|
|
// 마지막 콜론 이후 값(줌 레벨) 추출
|
|
|
|
|
if (identifier != null && identifier.contains(":")) {
|
|
|
|
|
String[] parts = identifier.split(":");
|
|
|
|
|
String zoomLevel = parts[parts.length - 1];
|
|
|
|
|
zoomLevels.add(zoomLevel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TileMatrixSetLink 객체 생성 및 추가
|
|
|
|
|
if (tileMatrixSet != null) {
|
|
|
|
|
WmtsLayerInfo.TileMatrixSetLink link =
|
|
|
|
|
new WmtsLayerInfo.TileMatrixSetLink(tileMatrixSet, zoomLevels);
|
|
|
|
|
links.add(link);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return links;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 특정 노드 아래의 자식 태그 값 추출 (예: <Title>값)
|
|
|
|
|
private String getChildValue(Node parent, String childName) {
|
|
|
|
|
Node child = findChildNode(parent, childName);
|
|
|
|
|
return (child != null) ? child.getTextContent() : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 특정 노드 아래의 반복되는 자식 구조 값 추출 (예: Keywords -> Keyword)
|
|
|
|
|
private List<String> getChildValues(Node parent, String wrapperName, String childName) {
|
|
|
|
|
List<String> results = new ArrayList<>();
|
|
|
|
|
Node wrapper = findChildNode(parent, wrapperName);
|
|
|
|
|
if (wrapper != null) {
|
|
|
|
|
NodeList children = wrapper.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().endsWith(childName)) {
|
|
|
|
|
results.add(node.getTextContent());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wrapper 없이 바로 반복되는 값 추출 (예: Format)
|
|
|
|
|
private List<String> getChildValuesDirect(Node parent, String childName) {
|
|
|
|
|
List<String> results = new ArrayList<>();
|
|
|
|
|
NodeList children = parent.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
if (node.getNodeName().endsWith(childName)) {
|
|
|
|
|
results.add(node.getTextContent());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 이름으로 자식 노드 찾기 (Local Name 기준)
|
|
|
|
|
private Node findChildNode(Node parent, String localName) {
|
|
|
|
|
NodeList children = parent.getChildNodes();
|
|
|
|
|
for (int i = 0; i < children.getLength(); i++) {
|
|
|
|
|
Node node = children.item(i);
|
|
|
|
|
// 네임스페이스 접두사(ows:, wmts:)를 무시하고 태그 이름 확인
|
|
|
|
|
if (node.getNodeName().endsWith(":" + localName) || node.getNodeName().equals(localName)) {
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getAttributeValue(Node node, String attrName) {
|
|
|
|
|
if (node.hasAttributes()) {
|
|
|
|
|
Node attr = node.getAttributes().getNamedItem(attrName);
|
|
|
|
|
if (attr != null) return attr.getNodeValue();
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|