【Godot4.2】MLTag类:HTML、XML通用标签类

概述

HTML和XML采用类似的标签形式。

之前在Godot中以函数库形式实现了网页标签和内容生成。能用,但是缺点也很明显。函数之间没有从属关系,但是多有依赖,而且没有划分出各种对象和类型。

如果以完全的面向对象形式来设计标签类或者元素类,将可以更贴近HTML或XML的本来面目。也更容易生成。

整体思路是设计如下的类继承结构:
在这里插入图片描述

实现之后,将可以充分的定义和生成HTML、XML和SVG标签,并用于内容生成或文档解析。

通用标签类

因为HTML和XML标签的语法格式和要素是类似的,因此可以通过创建一个通用的标签类,来生成HTML或XML标签。

MLtag就是这个通用的标签类,它定义了几个核心的属性:

  • tag_name :标签名称
  • attrs:包含标签所有属性的字典
  • is_single:是否为单标签,默认为false
  • content :标签的子内容,可以直接赋值,也可以使用append()方法追加。单标签(is_singletrue)时被忽略
  • get_end_tag():获取结束标签,单标签时返回空字符串
  • append():追加当前标签的子内容,可以是字符串形式,也可以是SVG标签实例(会自动调用to_string()方法转化为字符串)
# =============================================
# 名称:MLtag
# 类型:类
# 描述:HTMLXML通用标签类,用于定义和生成HTMLXML标签字符串
# 作者:巽星石
# 创建时间:202471617:48:01
# 最后修改时间:202471622:27:53
# =============================================
class_name MLTag

# ====================== 属性 ======================
var tag_name = ""          # 标签名称
var attrs:Dictionary = {}  # 属性字典
var is_single = false      # 是否单标签
var content = ""           # 子内容  

# ====================== 方法 ======================
# 获取结束标签
func get_end_tag() -> String:
	return "" if is_single else "</%s>" % tag_name

# 追加子内容
func append(new_content) -> void:
	if new_content is String:
		content += "\n" + new_content
	else:
		content += "\n" + new_content.to_string()

# ====================== 虚函数 ======================
# 转化为字符串
func _to_string() -> String:
	var tag_str:String
	
	# 获取属性字典的字符串
	var attr = ""
	for key in attrs.keys():
		if attrs[key] != "":
			attr += "%s=\"%s\" " % [key,attrs[key]]
	tag_str = "<%s%s/>" % [tag_name," " + attr] if is_single else "<%s%s>%s</%s>" % [tag_name," " + attr,content,tag_name]
	return tag_str

测试:

@tool
extends EditorScript

func _run() -> void:
	var tag = MLTag.new()    # 创建一个标签
	tag.name = "a"           # 名称
	tag.attrs["id"] = "a1"   # 设定属性
	tag.attrs["href"] = "https://www.runoob.com/"
	tag.content = "菜鸟教程"
	
	print(tag)

默认是双标签,也就是带有起始标签和结束标签的标签对。

<a id="a1" href="https://www.runoob.com/" >菜鸟教程</a>

is_single设为true后,就被认为是单标签:

@tool
extends EditorScript

func _run() -> void:
	var tag = MLTag.new()    # 创建一个标签
	tag.name = "a"           # 名称
	tag.attrs["id"] = "a1"   # 设定属性
	tag.attrs["href"] = "1.com"
	tag.innerHTML = "hahah"
	tag.is_single = true     # 设为标签
	
	print(tag)

打印输出的结果也就变了:

<a id="a1" href="https://www.runoob.com/" />

可以看到没有了结束标签,子内容部分也自动省略。

HTML标签基类

# =============================================
# 名称:HTMLtag
# 类型:类
# 描述:HTML标签基类
# 作者:巽星石
# 创建时间:202471619:05:46
# 最后修改时间:202471619:29:34
# =============================================
class_name HTMLTag extends MLTag

# ====================== 属性 ======================
# ID
var id:String:
	set(val):
		attrs["id"] = val
	get:
		return attrs["id"]
# name
var name:String:
	set(val):
		attrs["name"] = val
	get:
		return attrs["name"]
# css类名
var className:String:
	set(val):
		attrs["class"] = val
	get:
		return attrs["class"]
# 行内CSS样式
var style:String:
	set(val):
		attrs["style"] = val
	get:
		return attrs["style"]
# ====================== 初始化 ======================
func _init() -> void:
	# HTML标签通用属性
	attrs = {
		"id" = "",    # ID
		"name" = "",  # name属性
		"class" = "", # css类名
		"style" = "", # 行内样式
	}

测试代码:

@tool
extends EditorScript

func _run() -> void:
	var tag = HTMLTag.new()  # 创建一个标签
	tag.tag_name = "a"           # 名称
	# 设定HTML标签通用属性
	tag.id = "a2"
	tag.name = "a2"
	tag.className = "url"
	tag.style = "font-size:16px;"
	tag.innerHTML = "一个超链接"
	
	print(tag)

输出:

<a id="a2" name="a2" class="url" style="font-size:16px;" >一个超链接</a>

HTML<a>标签

# =============================================
# 名称:HTMLtagA
# 类型:类
# 描述:HTML<a>标签类
# 作者:巽星石
# 创建时间:202471619:32:47
# 最后修改时间:202471622:30:57
# =============================================
class_name HTMLTagA extends HTMLTag

# ====================== 属性 ======================
# 链接地址
var href:String:
	set(val):
		attrs["href"] = val
	get:
		return attrs["href"]
# 指定链接如何在浏览器中打开
var target:String:
	set(val):
		attrs["target"] = val
	get:
		return attrs["target"]
# 鼠标提示文本
var title:String:
	set(val):
		attrs["title"] = val
	get:
		return attrs["title"]
# 指定与链接目标的关系,如 nofollow、noopener 等
var rel:String:
	set(val):
		attrs["rel"] = val
	get:
		return attrs["rel"]

# ====================== 初始化 ======================
func _init() -> void:
	super()   # 初始化父类,否则无法继承相关的默认属性
	# 确定标签名称以及是否单标签
	tag_name = "a"
	is_single = false
	# <a>标签可用属性
	attrs["href"] = ""     # 链接地址
	attrs["target"] = ""   # 指定链接如何在浏览器中打开
	attrs["title"] = ""    # 鼠标提示文本
	attrs["rel"] = ""      # 指定与链接目标的关系,如 nofollow、noopener 等

测试代码:

@tool
extends EditorScript

func _run() -> void:
	var link = HTMLTagA.new()  # 创建一个标签
	# 设定<a>标签属性
	link.href = "https://www.runoob.com/"
	link.innerHTML = "菜鸟教程"
	
	print(link)

输出:

<a href="https://www.runoob.com/" >菜鸟教程</a>

SVG标签类

在这里插入图片描述

我发现专门做一个XML标签基类是没有必要的,XML本身就没有固定的标签,所以由MLTag定义完全可以解决XML标签定义和生成的功能。

<svg>本身既可以算HTML标签,也可以看做是XML标签。这里为了简化,我创建SVG类,代表<svg>标签,并直接继承自MLTag类型。

# =============================================
# 名称:SVG
# 类型:类
# 描述:SVG<svg>标签类
# 作者:巽星石
# 创建时间:202471621:37:24
# 最后修改时间:202471621:44:04
# =============================================
class_name SVG extends MLTag

# ====================== 属性 ======================
# SVG画布宽度
var width:String:
	set(val):
		attrs["width"] = val
	get:
		return attrs["width"]
# SVG画布高度
var height:String:
	set(val):
		attrs["height"] = val
	get:
		return attrs["height"]

# ====================== 初始化 ======================
func _init() -> void:
	tag_name = "svg"
	# HTML标签通用属性
	attrs = {
		"version"="1.1",
		"baseProfile"="full",
		"width"="200",
		"height"="200",
		"xmlns"="http://www.w3.org/2000/svg",
	}

SVGShape

SVG的形状和路径有许多共同的属性,所以抽象出一个SVGShape类型,用来承载共同属性。

# =============================================
# 名称:SVGShape
# 类型:类
# 描述:SVG所有形状和路径标签类的基类,承载共同属性
# 作者:巽星石
# 创建时间:202471621:51:00
# 最后修改时间:202471623:07:46
# =============================================
class_name SVGShape extends MLTag

# ====================== 属性 ======================
# 填充颜色
var fill:String:
	set(val):
		attrs["fill"] = val
	get:
		return attrs["fill"]

# 描边颜色
var stroke:String:
	set(val):
		attrs["stroke"] = val
	get:
		return attrs["stroke"]

# 描边宽度
var stroke_width:int:
	set(val):
		attrs["stroke-width"] = str(val)
	get:
		return int(attrs["stroke-width"])

# ====================== 初始化 ======================
func _init() -> void:
	tag_name = "svg"
	# svg形状和路径标签通用属性
	attrs["fill"] = "#fff"
	attrs["stroke"] = "#000"
	attrs["stroke-width"] = "1"

矩形

基于SVGShape类型,我们可以创建SVG具体的形状和路径类型。SVGRect就是SVG矩形 标签对应的类。

# =============================================
# 名称:SVGRect
# 类型:类
# 描述:SVG<rect>标签类
# 作者:巽星石
# 创建时间:202471621:47:43
# 最后修改时间:202471622:16:54
# =============================================
class_name SVGRect extends SVGShape

# ====================== 属性 ======================

# ---------------------- 位置 ---------------------- 
# 矩形左上角x坐标
var x:String:
	set(val):
		attrs["x"] = val
	get:
		return attrs["x"]

# 矩形左上角y坐标
var y:String:
	set(val):
		attrs["y"] = val
	get:
		return attrs["y"]
# ---------------------- 尺寸 ---------------------- 
# 矩形宽度
var width:String:
	set(val):
		attrs["width"] = val
	get:
		return attrs["width"]

# 矩形高度
var height:String:
	set(val):
		attrs["height"] = val
	get:
		return attrs["height"]
# ---------------------- 圆角 ---------------------- 
# 矩形圆角半径(水平方向)
var rx:String:
	set(val):
		attrs["rx"] = val
	get:
		return attrs["rx"]

# 矩形圆角半径(垂直方向)
var ry:String:
	set(val):
		attrs["ry"] = val
	get:
		return attrs["ry"]

# ====================== 初始化 ======================
func _init() -> void:
	super()   # 初始化父类,否则无法继承相关的默认属性
	tag_name = "rect"
	# HTML标签通用属性
	attrs["x"] = "0"
	attrs["y"] = "0"
	attrs["width"] = "100"
	attrs["height"] = "100"
	attrs["rx"] = "0"
	attrs["ry"] = "0"

测试代码:

@tool
extends EditorScript

func _run() -> void:
	var svg = SVG.new()          # 创建SVG标签
	var rect  = SVGRect.new()    # 创建矩形
	svg.append(rect)
	print(svg)

获得的SVG代码:

<svg version="1.1" baseProfile="full" width="200" height="200" xmlns="http://www.w3.org/2000/svg" >
<rect fill="#fff" stroke="#000" stroke-width="1" x="0" y="0" width="100" height="100" rx="0" ry="0" ></rect></svg>

SVG预览如下:
image.png

@tool
extends EditorScript

func _run() -> void:
	var svg = SVG.new(100,200)                    # 创建SVG标签
	var rect  = SVGRect.new(0,0,100,200,12,12)    # 创建矩形
	# 设定矩形属性
	rect.stroke = "red"
	rect.stroke_width = 2
	# 将矩形追加到svg内容的末尾
	svg.append(rect)
	print(svg)           # 打印SVG代码

获得的SVG代码:

<svg version="1.1" baseProfile="full" width="100" height="200" xmlns="http://www.w3.org/2000/svg" >
<rect fill="#fff" stroke="red" stroke-width="2" x="0" y="0" width="100" height="200" rx="12" ry="12" ></rect></svg>

预览如下:
image.png

总结

  • 纯面向对象的设计,尤其是基于继承的多个类组成的体系在某些方面还是很有用的。比如HTML、XML、SVG这样本身就很明显的继承设计。
  • 基于继承或许会写出一堆类,但是辅以类图和文档,还是能让别人比较轻松的理解和掌握的。
  • 静态函数库则完全是一个很差的设计形式,很有可能会被一堆函数搞得特别臃肿。
  • 适当的用类和类的继承形式取代静态函数库形式是我正在做的尝试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/801909.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

stm32精密控制步进电机(升级篇)

这一篇文章里会深入的对步进电机控制方法进行论述 如何避免步进电机丢转的问题 1.机械结构&#xff1a;排查一下传动的问题&#xff0c;举个例子&#xff0c;我的毕设里大臂机械臂的步进电机有时会有丢转问题&#xff0c;造成无法运动到指定位置&#xff0c;后面发现是因为皮带…

爬虫代理访问超时怎么解决?

一、为什么会出现访问超时 爬虫使用代理可能会遇到访问超时的情况&#xff0c;主要和以下几个方面有关&#xff1a; 1.代理服务器性能&#xff1a; 代理服务器作为中间层&#xff0c;承担着转发请求和响应的任务。如果代理服务器性能不佳或超载&#xff0c;请求的响应时间可能…

ELK日志管理

文章目录 一、ELK概述什么是ELK?为什么使用ELK&#xff1f;ELK的工作原理 二、安装部署ELK前期准备安装部署Elasticsearch 软件修改系统配置安装插件在应用服务器上部署 Logstash安装 kibana 一、ELK概述 什么是ELK? 通俗来讲&#xff0c;ELK 是由 Elasticsearch、Logstash…

LeetCode热题100刷题16:74. 搜索二维矩阵、33. 搜索旋转排序数组、153. 寻找旋转排序数组中的最小值、98. 验证二叉搜索树

74. 搜索二维矩阵 class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int row matrix.size();int col matrix[0].size();for(int i0;i<row;i) {//先排除一下不存在的情况if(i>0&&matrix[i][0]>target…

计算机网络——网络层(路由选择协议、路由器工作原理、IP多播、虚拟专用网和网络地址转换)

目录 路由选择协议 因特网的路由选择协议特点 路由信息协议RIP RIP衡量目的网络距离 RIP选择路由器的方式 RIP具有以下三个重要特点 RIP的基本工作流程 RIP的距离向量算法 ​编辑 ​编辑 RIP存在的问题——“坏消息传播得慢” RIP的封装 开放最短路径优先协议OSPF…

重学PyTorch,粗略笔记(二)dataset,dataloader

dataset 对于单个样本 dataloader 批量样本 Dataset 存储样本和它们相应的标签&#xff0c;DataLoader 在 Dataset 基础上添加了一个迭代器&#xff0c;迭代器可以迭代数据集&#xff0c;以便能够轻松地访问 Dataset 中的样本(变为mini-batch形式&#xff0c;多个样本组合成…

自动驾驶车道线检测系列—3D-LaneNet: End-to-End 3D Multiple Lane Detection

文章目录 1. 摘要概述2. 背景介绍3. 方法3.1 俯视图投影3.2 网络结构3.2.1 投影变换层3.2.2 投影变换层3.2.3 道路投影预测分支 3.3 车道预测头3.4 训练和真实值关联 4. 实验4.1 合成 3D 车道数据集4.2 真实世界 3D 车道数据集4.3 评估结果4.4 评估图像仅车道检测 5. 总结和讨论…

怎样在 PostgreSQL 中优化对多表关联的连接条件选择?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中优化对多表关联的连接条件选择一、理解多表关联的基本概念二、选择合适的连接条件…

深入解析HTTPS与HTTP

在当今数字化时代&#xff0c;网络安全已成为社会各界关注的焦点。随着互联网技术的飞速发展&#xff0c;个人和企业的数据安全问题日益凸显。在此背景下&#xff0c;HTTPS作为一种更加安全的通信协议&#xff0c;逐渐取代了传统的HTTP协议&#xff0c;成为保护网络安全的重要屏…

vue 实现下拉框的数据是树状结构

页面显示效果 vue实现代码 <el-form-item label"公司名称" prop"comName"><el-select ref"select" v-model"queryParams.comName" placeholder"请选择公司名称" clearable size"small"change"handl…

智慧医院智能导诊系统源码,智慧导诊小程序源码,采用前端框架:Uniapp+后端框架:springboot+移动端:微信小程序、H5自主研发

智慧导诊系统是一种基于人工智能和大数据技术的医疗辅助系统&#xff0c;旨在提高患者的就医效率和医院的管理效率。以下是对智慧导诊系统的详细解析&#xff1a; 定义与功能 智慧导诊系统通过自然语言处理、机器学习等技术&#xff0c;自动分析患者的病情及伴随症状&#xf…

Spring Boot集成Activity7实现简单的审批流

由于客户对于系统里的一些新增数据&#xff0c;例如照片墙、照片等&#xff0c;想实现上级逐级审批通过才可见的效果&#xff0c;于是引入了Acitivity7工作流技术来实现&#xff0c;本文是对实现过程的介绍讲解&#xff0c;由于我是中途交接前同事的这块需求&#xff0c;所以具…

模拟器小程序/APP抓包(Reqable+MUMU模拟器)

一、使用adb连接上MUMU模拟器 打开多开器点击ADB图标 连接模拟器端口&#xff1a; adb connect 127.0.0.1:16384列出已连接的设备&#xff1a; adb devices正常会显示MuMu的设备已连接 二、下载Reqable 1.下载链接&#xff1a;客户端下载 | Reqable 2.文档链接&#xff1a;…

昇思25天学习打卡营第12天|LLM-基于MindSpore实现的BERT对话情绪识别

打卡 目录 打卡 预装环境 BERT 任务说明 数据集 数据加载和数据预处理&#xff1a;process_dataset 函数 模型构建与训练 运行示例 模型验证 模型推理 自定义推理数据集 运行结果示例 代码 预装环境 pip install -i https://pypi.mirrors.ustc.edu.cn/simple min…

使用ant+jmeter如何生成html报告

一、安装ant 下载apache-ant&#xff0c;放到对应路径下&#xff0c;然后进行环境变量配置。系统变量的CLASSPATH添加E:\Installation Pack\eclipse\apache-ant-1.9.6\lib;用户变量的PATH添加&#xff1a;E:\Installation Pack\eclipse\apache-ant-1.9.6\bin。打开cmd&#xf…

持续集成02--Linux环境更新/安装Java新版本

前言 在持续集成/持续部署&#xff08;CI/CD&#xff09;的旅程中&#xff0c;确保开发环境的一致性至关重要。本篇“持续集成02--Linux环境更新/安装Java新版本”将聚焦于如何在Linux环境下高效地更新或安装Java新版本。Java作为广泛应用的编程语言&#xff0c;其版本的更新对…

前端框架入门之Vue的模版语法与数据单向绑定 数据双向绑定

目录 vue的模版语法 数据绑定 vue的模版语法 关于模版这个概念 root容器里面被称为模版 我们的语法分为插值语法和插值语法 这样就是实现了插值语法 接下来我们实现指令语法 首先我们写一个a标签 链一个超链接上去 <h1>指令语法</h1><a href"https:/…

【46 Pandas+Pyecharts | 当当网畅销图书榜单数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 去除重复数据2.4 书名处理2.5 提取年份 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 作者图书数量分布3.2 图书出版年份…

openeuler 终端中文显示乱码、linux vim中文乱码

1、解决终端乱码 网上很多教程试了都不生效&#xff0c;以下方法有效&#xff1a; 确认终端支持中文显示&#xff1a; echo $LANG 输出应该包含 UTF-8&#xff0c;例如 en_US.UTF-8。如果不是&#xff0c;您可以通过以下命令设置为 UTF-8&#xff1a; export LANGzh_CN.UTF-8…

昇思25天学习打卡营第12天|Vision Transformer图像分类、SSD目标检测

Vision Transformer&#xff08;ViT&#xff09;简介 近些年&#xff0c;随着基于自注意&#xff08;Self-Attention&#xff09;结构的模型的发展&#xff0c;特别是Transformer模型的提出&#xff0c;极大地促进了自然语言处理模型的发展。由于Transformers的计算效率和可扩…