XSLT - 使用名称值对字典填充XML表单输入

时间:2017-10-15 16:45:01

标签: xml asp.net-mvc xslt

我有一个表单的xml模板,使用xslt进行渲染,如下所示:

的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文件。

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

有没有人有任何其他建议或解决方法。一些代码片段也会有所帮助,因为我不能很好地使用xsl / xml

注意我试图在.Net MVC

中实现这一点

2 个答案:

答案 0 :(得分: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>  

答案 1 :(得分:0)

如果你想在XSLT中表示一个.NET字典,那么你可能希望移动到Saxon 9.8 HE(在XSLT 3.0和Sourceforge上可用)支持的NuGet,你可以{{3}进入convert it

然后你的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)类型的参数,然后你可以将它用作函数调用@name中传递$field-map(@name) map / dictionary键的函数。 / p>

运行上面的C#片段,传入字典并写出带有转换结果的字符串

        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属性。