jQuery 导航 XML 父子节点并从每个子节点中选择适当的属性
jQuery navigating XML parent child nodes and selecting appropriate attributes from each?
我正在创建一个模板系统,该系统可以在客户端使用 Javascript 进行解释,以构建填充空白表单,例如给客户的一封信等。
我已经用伪代码构建了模板和逻辑,但是我对jQuery的不熟悉,我可以使用一些方向来开始。
基本思想是在我的文本节点中有一个标记,表示一个字段,例如 ${prologue},然后将其添加到名为"fields"的数组中,然后用于在 xml 中搜索相应的节点名称。
.XML
<?xml version="1.0" encoding="UTF-8"?>
<message>
<text>${Prologue} - Dear ${Title} ${Surname}. This is a message from FUBAR. An engineer called but was unable to gain access, a new appointment has been made for ${ProductName} with order number ${VOLNumber}, on ${AppointmentDate} between ${AppointmentSlot}.
Please ensure you are available at your premises for the engineer. If this is not convenient, go to fubar.com or call 124125121515 before 12:00 noon the day before your appointment. Please refer to your order confirmation for details on what will happen on the day. ${Epilogue} - Free text field for advisor input<
</text>
<inputTypes>
<textBox type="text" fixed="n" size="100" alt="Enter a value">
<Prologue size="200" value="BT ENG Appt Reschedule 254159" alt="Prologue field"></Prologue>
<Surname value="Hoskins"></Surname>
<ProductName value=""></ProductName>
<VOLNumber size="8" value="" ></VOLNumber>
<Epilogue value=""></Epilogue>
</textBox>
<date type="datePicker" fixed="n" size="8" alt="Select a suitable appointment date">
<AppointmentDate></AppointmentDate>
</date>
<select type="select" >
<Title alt="Select the customers title">
<values>
<Mr selected="true">Mr</Mr>
<Miss>Miss</Miss>
<Mrs>Mrs</Mrs>
<Dr>Dr</Dr>
<Sir>Sir</Sir>
</values>
</Title>
<AppointmentSlot alt="Select the appointment slot">
<values>
<Morning>9:30am - 12:00pm</Morning>
<Afternoon>1:00pm - 5:00pm</Afternoon>
<Evening>6:00pm - 9:00pm</Evening>
</values>
</AppointmentSlot>
</select>
</inputTypes>
</message>
伪代码
Get list of tags from text node and build array called "fields"
For each item in "fields" array:
Find node in xml that equals array item's name
Get attributes of that node
Jump to parent node
Get attributes of parent node
If attributes of parent node != child node then ignore
Else add the parent attributes to the result
Build html for field using all the data gathered from above
增编
这个逻辑可以吗,是否可以从节点的父节点开始向下导航?
同样关于继承,我们是否可以获取父属性,如果子属性不同,则将它们添加到结果中?如果父属性中的属性数不等于子项中的属性数怎么办?
请不要提供完全编码的解决方案,只是一些预告片让我入门。
这是我到目前为止所拥有的,它正在从文本节点中提取标签
//get value of node "text" in xml
var start = $(xml).find("text").text().indexOf('$');
var end = $(xml).find("text").text().indexOf('}');
var tag = "";
var inputType;
// find all tags and add them to a tag array
while (start >= 0)
{
//console.log("Reach In Loop " + start)
tag = theLetter.slice(start + 2, end);
tagArray.push(tag);
tagReplaceArray.push(theLetter.slice(start, end + 1));
start = theLetter.indexOf('$', start + 1);
end = theLetter.indexOf('}', end + 1);
}
欢迎提出任何其他建议或与类似问题的链接。
谢谢!
我正在使用类似的技术来做 html 模板化。
我发现使用字符串然后将其转换为 html 更容易,而不是使用元素。在使用jQuery的情况下,您可以执行类似操作:
将 xml 作为字符串:
var xmlString='<?xml version="1.0" encoding="UTF-8"?><message><text>${Prologue} - Dear ${Title} ${Surname}... ';
遍历字符串以使用正则表达式进行替换(1 是捕获的占位符,例如姓氏):
xmlString.replace(/$'{([^}]+)}/g,function($0,$1)...}
如果需要,转换为节点:
var xml=$(xmlString);
正则表达式的好处:
- 更快(只是一个字符串,你不是在走 DOM)
- 全局替换(例如,如果 Surname 出现多次),只需遍历一次对象属性即可
- 简单正则表达式/${([^}]+)}/以定位占位符
从文本节点获取标签列表并构建名为"fields"的数组
要创建数组,我宁愿使用正则表达式,这是它的最佳用途之一(在我看来),因为我们确实在寻找一种模式:
var reg = /'$'{('w+)'}/gm;
var i = 0;
var fields = new Array();
while ( (m = reg.exec(txt)) !== null)
{
fields[i++] = m[1];
}
对于"字段"数组中的每个项目
jQuery提供了一些实用功能:
要遍历您的字段,您可以这样做: $.each(fields, function(index, value){});
在节点中导航并检索值
只需像您已经做的那样使用 jQuery 函数即可。
构建 HTML
我会为您负责的每种类型创建模板对象(在本例中:Text
、Select
)
然后使用上述模板,您可以将令牌替换为模板的 HTML。
显示 HTML
最后一步是解析结果字符串并将其附加到正确的位置:
var ResultForm = $.parseHTML(txt);
$("#DisplayDiv").append(ResultForm);
结论
就像你问的,我没有准备任何开箱即用的东西,我希望它能帮助你准备自己的答案。(然后我希望你能与社区分享)
这只是一个让你前进的框架,就像你问的那样。
第一个概念是使用正则表达式来查找 ${ } 的所有匹配项。 它返回一个数组,如 ["${one}","${t w 0 }","${ three}"]。
第二个概念是htmlGenerator json对象将"inputTypes-->childname"映射到负责html打印输出的函数。
第三是不要忘记自然的JavaScript。 .localname
会给你xml元素的名字,node.attributes
应该给你一个namedNodeMap(记住不要对jquery对象执行自然的javascript,确保你引用的是为你找到的节点元素jQuery)。
实际流程很简单。
找到所有 '${}' 令牌并将结果存储在数组中。
在 XML 文档中查找所有令牌,并使用其父项信息,将 HTML 存储在{"${one}":"<input type='text' .../>","${two}":"<select><option value='hello'>world!</option></select>" ...}
映射中
循环访问地图,并将源文本中的每个标记替换为所需的 HTML。
JavaScript
var $xmlDoc = $(xml); //store the xml document
var tokenSource =$xmlDoc.find("message text").text();
var tokenizer=/${[^}]+/g; //used to find replacement locations
var htmlGenerators = {
"textBox":function(name,$elementParent){
//default javascript .attributes returns a namedNodeMap, I think jquery can handle it, otherwise parse the .attributes return into an array or json obj first.
var parentAttributes = ($elementParent[0] && $elementParent.attributes)?$elementParent.attributes:null;
//this may be not enough null check work, but you get the idea
var specificAttributes =$elementParent.find(name)[0].attributes;
var combinedAttributes = {};
if(parentAttributes && specificAttributes){
//extend or overwrite the contents of the first obj with contents from 2nd, then 3rd, ... then nth [$.extend()](http://api.jquery.com/jQuery.extend/)
$.extend(combinedAttributes,parentAttributes,specificAttributes);
}
return $("<input>",combinedAttributes);
},
"date":function(name,$elementParent){
//whatever you want to do for a 'date' text input
},
"select":function(name,$elementParent){
//put in a default select box implementation, obviously you'll need to copy options attributes too in addition to their value / visible value.
}
};
var html={};
var tokens = tokenSource.match(tokenizer); //pull out each ${elementKey}
for(index in tokens){
var elementKey = tokens[index].replace("${","").replace("}"),"");//chomp${,}
var $elementParent = $xmlDoc.find(elementKey).parent();//we need parent attributes. javascript .localname should have the element name of your xml node, in this case "textBox","date" or "select". might need a [0].localname....
var elementFunction = ($elementParent.localname)?htmlGenerators[elementParent.localname]:null; //lookup the html generator function
if(elementFunction != null){ //make sure we found one
html[tokens[index]] = elementFunction(elementKey,elementParent);//store the result
}
}
for(index in html){
//for every html result, replace it's token
tokenSource = tokenSource.replace(index,html[index]);
}
- 选择<李>使用普通JavaScript的子节点,而不是孙节点
- 从 d3.js 中的树中选择节点的子节点
- 难以获取使用属性选择的节点的子节点
- 按属性从子节点中选择节点
- 无法在 Javascript 代码中选择子节点
- jquery选择器可以选择所有具有子节点的元素与某些条件匹配
- 在树布局中选择子节点的所有路径和父节点
- 在jstree中选择子节点时,检查所有父节点
- jtree -禁用负载时的子节点自动选择
- 如何在没有选择器的情况下从父节点获取子节点
- 选择没有特定索引的子节点(Jquery)
- 如何使用此选择器查找直接子节点
- 不能选择子节点
- 选择子节点(DOM)
- 如何在树视图中选择父节点时选择所有子节点?(当treeview从usercontrol中使用时)
- 选择/取消选择递归子节点在点击最上面的节点
- 在d3中选择子节点的位置
- jquery.find()是否只能选择直接子节点?
- 使用Javascript选择同级节点的子节点
- 选择一个具有具有特定值的子节点的特定节点