【问题标题】:jQuery navigating XML parent child nodes and selecting appropriate attributes from each?jQuery 导航 XML 父子节点并从每个子节点中选择适当的属性?
【发布时间】:2013-02-04 12:00:40
【问题描述】:

我正在创建一个模板系统,该系统可以在客户端使用 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

附录

这个逻辑可以吗,是否可以从节点的父节点开始向下导航?

关于继承,我们能否获得父属性,如果子属性不同,则将它们添加到结果中?如果 parent 中的属性数量不等于 child 中的数量怎么办?

请不要提供完全编码的解决方案,只是为了让我开始。

这是我目前从文本节点中提取标签的内容

//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);
    }

欢迎任何其他建议或类似问题的链接。

谢谢!

【问题讨论】:

  • 您控制 XML 生成吗?那是在其他一些过程中你可能会改变它吗?
  • 不,假设我无法控制它
  • 你为什么给“loosebruce”-1?在我发布此评论时,它已经是-4,没有任何解释。是否符合 StackOverflow 礼仪?

标签: javascript jquery xml xml-parsing


【解决方案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)
  • 全局替换(例如,如果姓氏出现多次),只需循环一次对象属性
  • 简单的正则表达式 /${([^}]+)}/ 来定位占位符

【讨论】:

  • @loosebruce 你觉得因为问题中缺少信息而对答案投反对票公平吗?
  • @Christophe 对您的回答投反对票并不好,但这是对此投反对票的解释。我也觉得这个解释是错误的。宽松的布鲁斯有很多没有任何解释的反对票——我认为这不好。我给了你+1
  • @MikroDel 我和你在一起,人们应该解释一个反对票,我不知道为什么 stackoverflow 没有强制要求。如您所知,版主已经对这篇文章进行了一些清理,一些来自loosbruce 的初始 cmets 可能会解释反对意见。
【解决方案2】:

从文本节点获取标签列表并构建名为“fields”的数组

要创建数组,我宁愿使用regular expression,这是它的最佳用途之一(在我看来),因为我们确实在寻找一种模式:

var reg = /\$\{(\w+)\}/gm;
var i = 0;
var fields = new Array();

while (  (m = reg.exec(txt)) !== null)
{
    fields[i++] = m[1];
}

对于“fields”数组中的每一项

jQuery 提供了一些utility functions

要遍历您的字段,您可以这样做:$.each(fields, function(index, value){});

浏览节点并检索值

就像你已经在做的那样使用jQuery function

构建 HTML

我将为您负责的每种类型创建模板对象(在此示例中:TextSelect

然后使用上述模板,您可以将标记替换为模板的 HTML。

显示 HTML

最后一步是解析结果字符串并将其附加到正确的位置:

var ResultForm = $.parseHTML(txt); 

$("#DisplayDiv").append(ResultForm);

结论

就像你问的那样,我没有准备任何开箱即用的东西,我希望它能帮助你准备好自己的答案。 (然后我希望你能与社区分享)

【讨论】:

    【解决方案3】:

    这只是一个框架,可以让你如你所愿。

    第一个概念是使用正则表达式来查找 ${ } 的所有匹配项。它返回一个类似 ["${one}","${t w 0 }","${ three}"] 的数组。

    第二个概念是一个htmlGenerator json对象映射“inputTypes-->childname”到一个负责html打印输出的函数。

    第三是不要忘记自然的javascript。 .localname 会给你 xml 元素的名称,node.attributes should 给你一个 namedNodeMap 回来(记住不要对 jquery 对象执行自然 javascript,确保你引用的是 jQuery 为你找到的节点元素)。

    实际流程很简单。

    找到所有的 '${}' 标记并将结果存储在一个数组中。

    在 xml 文档中找到所有标记并使用它们的父信息,将 html 存储在 {"${one}":"&lt;input type='text' .../&gt;","${two}":"&lt;select&gt;&lt;option value='hello'&gt;world!&lt;/option&gt;&lt;/select&gt;" ...} 的映射中

    遍历地图并将源文本中的每个标记替换为您想要的 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]);
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多