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

news/2024/9/18 8:14:46/ 标签: html, xml, godot, gdscript, SVG, 文档解析, 面向对象
xmlns="http://www.w3.org/2000/svg" style="display: none;">

概述

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

测试代码:

@tool
extends EditorScriptfunc _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"] = valget:return attrs["href"]
# 指定链接如何在浏览器中打开
var target:String:set(val):attrs["target"] = valget:return attrs["target"]
# 鼠标提示文本
var title:String:set(val):attrs["title"] = valget:return attrs["title"]
# 指定与链接目标的关系,如 nofollow、noopener 等
var rel:String:set(val):attrs["rel"] = valget: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 EditorScriptfunc _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_239">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"] = valget:return attrs["width"]
# SVG画布高度
var height:String:set(val):attrs["height"] = valget: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_282">SVGShape

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

# =============================================
# 名称:SVGShape
# 类型:类
# 描述:SVG所有形状和路径标签类的基类,承载共同属性
# 作者:巽星石
# 创建时间:202471621:51:00
# 最后修改时间:202471623:07:46
# =============================================
class_name SVGShape extends MLTag# ====================== 属性 ======================
# 填充颜色
var fill:String:set(val):attrs["fill"] = valget:return attrs["fill"]# 描边颜色
var stroke:String:set(val):attrs["stroke"] = valget: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"] = valget:return attrs["x"]# 矩形左上角y坐标
var y:String:set(val):attrs["y"] = valget:return attrs["y"]
# ---------------------- 尺寸 ---------------------- 
# 矩形宽度
var width:String:set(val):attrs["width"] = valget:return attrs["width"]# 矩形高度
var height:String:set(val):attrs["height"] = valget:return attrs["height"]
# ---------------------- 圆角 ---------------------- 
# 矩形圆角半径(水平方向)
var rx:String:set(val):attrs["rx"] = valget:return attrs["rx"]# 矩形圆角半径(垂直方向)
var ry:String:set(val):attrs["ry"] = valget: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 EditorScriptfunc _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 EditorScriptfunc _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.ppmy.cn/news/1475913.html

相关文章

信创终端系统上使用Pillow库调整图片大小 | 统信 | 麒麟 | 中科方德

原文链接&#xff1a;信创终端系统上使用Pillow库调整图片大小 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在信创终端系统上使用Pillow库调整图片大小的文章。Pillow是Python Imaging Library&#xff08;PIL&#xff09;的一个分支&#xff0c;是一个非常强…

【Git 学习笔记】第五章 在 Git 仓库存入附加信息(上)

第五章 在 Git 仓库存入附加信息 相关主题 添加第一条 Git 笔记按类别区分 Git 笔记从远程库读取 Git 笔记推送 Git 笔记到远程库为 commit 版本添加标签 Git 最强大的一个特性&#xff0c;在于它的提交历史 永不可改变。这意味着任何试图篡改仓库历史的行为&#xff0c;对于其…

排序-java(详解)

一&#xff0c;分类 主要的排序大致分为以下几类&#xff1a; 1&#xff0c;插入排序&#xff0c;又分为直接插入排序和希尔排序 2&#xff0c;选择排序&#xff0c;又分为选择排序和堆排序 3&#xff0c;交换排序&#xff0c;又分为冒泡排序和快速排序 4&#xff0c;归并…

论文翻译:通过云计算对联网多智能体系统进行预测控制

通过云计算对联网多智能体系统进行预测控制 文章目录 通过云计算对联网多智能体系统进行预测控制摘要前言通过云计算实现联网的多智能体控制系统网络化多智能体系统的云预测控制器设计云预测控制系统的稳定性和一致性分析例子结论 摘要 本文研究了基于云计算的网络化多智能体预…

第九课:服务器发布(静态nat配置)

一个要用到静态NAT的场景&#xff0c;当内网有一台服务器server1&#xff0c;假如一个用户在外网&#xff0c;从外网访问内网怎么访问呢&#xff0c;无法访问&#xff0c;这是因为外网没办法直接访问内网&#xff0c;这时候需要给服务器做一个静态NAT。 静态NAT指的是给服务器…

Html_Css问答集(8)

52、在网页设计中有一个目录assets一般表示什么意思 "Assets" 的英文原意是 资产。 在网页设计中&#xff0c;我们使用 "assets" 文件夹来存放网站的静态资源文件&#xff0c;就像把这些资源看作是网站的“资产”一样。 assets 文件夹中的静态资源…

使用Spring Boot实现分布式配置管理

使用Spring Boot实现分布式配置管理 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. 什么是分布式配置管理&#xff1f; 在分布式系统中&#xff0c;配置管理是一项重要的任务。它涉及到管理和集…

N叉树的前序遍历

Problem: 589. N 叉树的前序遍历 文章目录 思路解题过程Code 思路 前序遍历&#xff0c;遇到空节点返回 解题过程 对每个节点进行遍历 Code /* // Definition for a Node. class Node { public:int val;vector<Node*> children;Node() {}Node(int _val) {val _val;}Nod…

Nature Pixels V2 | Top-down pixel art asset pack

Nature Pixels V2可以用于自上而下的视图游戏&#xff0c;使其看起来更好&#xff01; 如果你喜欢这个资产包&#xff0c;一定要在评论中告诉我&#xff01;祝你今天过得愉快 所容纳之物 16x16瓷砖&#xff0c;可以帮助你用100多块瓷砖构建自己的美丽世界 房屋 岩石 树 墙壁 水…

Java(二十)---双向链表

文章目录 前言1.为什么学习双向链表2.双向链表(LinkedList)的模拟实现2.1. 准备工作2.2.功能的实现2.2.1.显示链表(display) 和 是否包含某种元素(contains) 以及 获取链表节点个数(size())2.2.2.头插法(addFirst)&#xff0c;尾插法(addLast)&#xff0c;以及在指定位置进行插…

RK3568 V1.4.0 SDK,USB OTG端子不能被电脑识别出adb设备,解决

修改后的/usr/bin/usbdevice: #!/bin/sh # # Usage: # usbdevice [start|update|stop] # # Hookable stages: # usb_<pre|post>_<init|prepare|start|stop|restart>_hook # <usb function>_<pre|post>_<prepare|start|stop>_hook # # Example …

第三方配件也能适配苹果了,iOS 18与iPadOS 18将支持快速配对

苹果公司以其对用户体验的不懈追求和对创新技术的不断探索而闻名。随着iOS 18和iPadOS 18的发布&#xff0c;苹果再次证明了其在移动操作系统领域的领先地位。 最新系统版本中的一项引人注目的功能&#xff0c;便是对蓝牙和Wi-Fi配件的配对方式进行了重大改进&#xff0c;不仅…

【LabVIEW学习篇 - 6】:数组、簇

文章目录 数组创建数组数组函数数组大小 根据索引取值数组与for循环 案例一案例二 簇LabVIEW簇的特点和用途&#xff1a;创建簇解除捆绑按名称解除捆绑簇的捆绑重新排序簇中控件 数组 在LabVIEW中&#xff0c;数组是一种用于存储相同数据类型的多个元素的数据结构。以下是关于…

技术探索之kotlin浅谈

Kotlin是一种静态类型编程语言&#xff0c;它运行在Java虚拟机&#xff08;JVM&#xff09;上&#xff0c;可以与Java代码互操作。Kotlin由JetBrains开发&#xff0c;是一种现代、简洁且安全的编程语言。它在2011年首次亮相&#xff0c;2017年被谷歌宣布为Android官方开发语言。…

作业7.16

第一题&#xff1a; 在终端的界面上输出:__-__-__-__ 1秒过后&#xff0c; 变成 1_-__-__-__ 再1秒过后&#xff0c;变成 12-__-__-__ 依此类推 经过8秒&#xff0c;最终变成 12-34-56-78 \b 是printf里面&#xff0c;光标向左移动的转义符 #include <stdio.h> #include …

视频使用操作说明书-T80004系列视频编码器如何对接海康NVR硬盘录像机,包括T80004系列高清HDMI编码器、4K超高清HDMI编码器

视频使用操作说明书-T80004系列视频编码器如何对接海康NVR硬盘录像机&#xff0c;包括T80004系列高清HDMI编码器、4K超高清HDMI编码器。 视频使用操作说明书-T80004系列视频编码器如何对接海康NVR硬盘录像机(不带屏)&#xff0c;包括T80004系列高清HDMI编码器、4K超高清HDMI编码…

hid.dll丢失怎么办?hid.dll丢失解决步骤分享

hid.dll&#xff0c;即Human Interface Device Dynamic Link Library&#xff0c;是Windows操作系统中用于管理人机交互设备&#xff08;HID&#xff09;的核心组件。这些设备包括但不限于键盘、鼠标、游戏控制器等。该DLL文件确保这些设备能够与操作系统顺畅通信&#xff0c;实…

ECCV`24 | 编辑能力无上限!北航谷歌旷视等开源Chat-Edit-3D: 3D 场景编辑新范式!

文章链接&#xff1a;https://arxiv.org/abs/2407.06842 项目地址&#xff1a;https://sk-fun.fun/CE3D/ 代码&#xff1a;https://github.com/Fangkang515/CE3D/tree/main 引言 过去的3D场景编辑方法往往局限于固定的文本输入模式和有限的编辑能力。用户需要学习特定的命令或…

前端打包部署后源码安全问题总结

随着现代Web应用越来越依赖于客户端技术&#xff0c;前端安全问题也随之突显。源码泄露是一个严重的安全问题&#xff0c;它不仅暴露了应用的内部逻辑和业务关键信息&#xff0c;还可能导致更广泛的安全风险。本文将详细介绍源码泄露的潜在风险&#xff0c;并提供一系列策略和工…

C语言经典程序100案例

C语言经典程序100题(完整版) 【程序1】题目&#xff1a;有1、2、3、4个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数都是多少 程序分析&#xff1a;可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去掉不满足条件的排列。 #include "stdio…