【问题标题】:XSLT - Populate XML Form Inputs with Name Value Pair DictionaryXSLT - 使用名称值对字典填充 XML 表单输入
【发布时间】:2018-03-27 05:11:50
【问题描述】:

我有一个使用 xslt 呈现的表单的 xml 模板,如下所示:

xml:

<form-template>
  <fields>
    <field type="text" required="true" label="Subject" class="form-control" name="subject" subtype="text"></field>
    <field type="textarea" required="true" label="Description" class="form-control" name="description" subtype="textarea" rows="3"></field>
  </fields>
</form-template>

xsl:

<xsl:template match="/*">
     <xsl:for-each select="fields/field">  
         <xsl:if test="@type='text'"> 
            <label for="{@name}"><xsl:value-of select="@label"/></label>
            <input class="form-control" data-val="{@required}" data-val-required="The {@label} field is required." id="{@name}" name="{@name}" type="text" value=""></input>
            <span class="field-validation-valid" data-valmsg-for="{@name}" data-valmsg-replace="true"></span>
          </xsl:if> 
     </xsl:for-each>  
</xsl:template>

使用自定义 HTMLHelper 呈现表单。

 @Html.RenderXml(Model.Template, Server.MapPath("~/Content/form.xslt"))

值存储为名称/值对:

var values = new Dictionary<string, string> {{"subject", "This is the subject"}, {"description", "This is the description"}};

如何将这些值传递给 xsl 并针对 xml 模板中的每个表单字段进行迭代,如果名称与字段名称匹配,则使用该值填充相应的字段。

我已经四处搜索,但看不到如何将数组类型变量传递给 xsl 文件。

我是否将字典转换为节点集并将其作为argumentlist参数传递?

有没有人有任何其他建议或解决方法。一些代码 sn-p 也会很有帮助,因为我不擅长使用 xsl/xml

请注意,我正在尝试在 .Net MVC 中实现这一目标

【问题讨论】:

    标签: xml asp.net-mvc xslt


    【解决方案1】:

    我已经管理了类似于 Martin Honnen 的答案,但没有迁移到 xslt 3.0

    以下是我所做的。我通过添加 xsltargument 并将字典转换为 XPathNodeIterator 来更新 HTML 帮助器:

     var args = new XsltArgumentList();
     var dict = new Dictionary<string, string> {{ "subject", "This is the subject" }, { "description", "This is the description" }};
     var el = new XElement("keyvalues", dict.Select(kv => new XElement("keyvalue", new XAttribute("key", kv.Key), new XAttribute("value", kv.Value))));
     args.AddParam("keyvalues", "", el.CreateNavigator());
    

    在我的 xslt 中我更新如下:

    <xsl:param name="keyvalues"/>  
    <xsl:template match="/*">
     <xsl:for-each select="fields/field">  
         <xsl:if test="@type='text'"> 
            <label for="{@name}"><xsl:value-of select="@label"/></label>
            <input class="form-control" data-val="{@required}" data-val-required="The {@label} field is required." id="{@name}" name="{@name}" type="text" value="{$keyvalues/keyvalue[@key = current()/@name]/@value}"></input>
            <span class="field-validation-valid" data-valmsg-for="{@name}" data-valmsg-replace="true"></span>
          </xsl:if> 
     </xsl:for-each>  
    

    【讨论】:

      【解决方案2】:

      如果您想在 XSLT 中表示一个 .NET 字典,那么您可能需要移动到 Saxon 9.8 HE 支持的 XSLT 3.0(在 NuGet 和 Sourceforge 上可用),您可以将 convert it 转换为 @987654324 @。

      那么你的 XSLT 会是这样的

      <xsl:stylesheet version="3.0"
                      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                      xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"
      >
        <xsl:param name="field-map" as="map(xs:string, xs:string)" required="yes"/>
      
        <xsl:output method="html" indent="yes"/>
      
        <xsl:template match="/*">
          <xsl:for-each select="fields/field">
            <xsl:if test="@type='text'">
              <label for="{@name}">
                <xsl:value-of select="@label"/>
              </label>
              <input class="form-control" data-val="{@required}" data-val-required="The {@label} field is required." id="{@name}" name="{@name}" type="text" value="{$field-map(@name)}"></input>
              <span class="field-validation-valid" data-valmsg-for="{@name}" data-valmsg-replace="true"></span>
            </xsl:if>
          </xsl:for-each>
        </xsl:template>
      
      </xsl:stylesheet>
      

      (所以基本上你声明了一个map(xs:string, xs:string) 类型的参数,然后你可以将它用作一个函数,在函数调用$field-map(@name) 中传入你的@name map/dictionary 键)。

      一个C# sn -p 运行上面的,传入字典并用转换结果写出一个字符串

              var values = new Dictionary<string, string> { { "subject", "This is the subject" }, { "description", "This is the description" } };
              XdmMap mapParam = XdmMap.MakeMap(values);
      
              Processor proc = new Processor();
      
              Uri baseUri = new Uri(new FileInfo(".").FullName);
      
              XmlResolver resolver = new XmlUrlResolver();
      
      
              Xslt30Transformer transformer = proc.NewXsltCompiler().Compile(resolver.ResolveUri(baseUri, "sheet1.xslt")).Load30();
      
              transformer.SetStylesheetParameters(new Dictionary<QName, XdmValue> { { new QName("field-map"), mapParam } });
      
              Serializer serializer = proc.NewSerializer();
      
              using (StringWriter sw = new StringWriter())
              {
                  serializer.SetOutputWriter(sw);
                  using (FileStream fs = File.OpenRead(@"template1.xml"))
                  {
                      transformer.ApplyTemplates(fs, serializer);
                  }
                  Console.WriteLine(sw.ToString());
              }
      

      我得到的输出是例如

      <label for="subject">Subject</label><input class="form-control" data-val="true" data-val-required="The Subject field is required." id="subject" name="subject" type="text" value="This is the subject"><span class="field-validation-valid" data-valmsg-for="subject" data-valmsg-replace="true"></span>
      

      所以value 属性已设置。

      【讨论】:

      • 谢谢。我也管理过类似的事情 - 请参阅上面的答案。
      猜你喜欢
      • 2019-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 1970-01-01
      • 2014-05-19
      相关资源
      最近更新 更多