如何在配置文件中放置模板/继承?

时间:2010-12-21 00:32:24

标签: xml templates inheritance configuration

我正在研究一个包含各种类别对象的模型,每个对象都有各种版本。我想在配置文件中将这些作为默认值提供,但也允许用户轻松自定义默认值。

这就是一般情况:

<containers>
  <container1>
    <object1>
      <param1>42</param1>
      <param2>3.14159</param2>
    </object1>
    <object2>
      <param3>2.71828</param3>
      <param4>auto</param4>
    </object2>
  </container1>
</containers>

我想处理下一个块,并使得到的对象结构与前一个块创建的对象结构相同。

<templates>
  <object1 id="object1_1.0">
    <param1>42</param1>
    <param2>1</param2>
  </object1>
  <object2 id="object2_1.0">
    <param3>2</param3>
    <param4>auto</param4>
  </object2>
</templates>
<containers>
  <container1>
    <object1 ref="object1_1.0">
      <!--param1 "inherited" as "42"-->
      <param2>3.14159</param2>
    </object1>
    <object2 ref="object2_1.0">
      <param3>2.71828</param3>
      <!--param4 "inherited" as "auto"-->
    </object2>
  </container1>
</containers>

也就是说,我希望能够通过读取这两个不同的输入文件来获得相同的树。我期望读取XML,然后在生成对象树之前处理生成的树。

我一直无法在其他项目中找到任何对此进行的引用 - 我甚至不确定如何搜索它。如果你这样做了,你是怎么做到的?否则,你觉得怎么样?或者你试过这个并发现它比它的价值更复杂吗?

2 个答案:

答案 0 :(得分:1)

您可以使用xslt,如:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:template match="/">
    <xsl:apply-templates select="@*|node()"/>
</xsl:template>

<!-- Process all containers -->
<xsl:template match="containers">
    <xsl:for-each select="child::node()">
        <!--Copy Container node  -->
        <xsl:copy>
            <xsl:for-each select="child::node()">
                <xsl:copy>
                    <!-- first copy template node -->
                    <xsl:for-each select="//node()[@id=current()/attribute::ref]/child::node()">
                        <xsl:copy>
                            <xsl:apply-templates select="@*|node()"/>
                        </xsl:copy>
                    </xsl:for-each>
                    <!--Then the object nodes -->
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:for-each>
</xsl:template>

<!-- =====================================================
 recursive copy,
 but skip templates nodes and ref attributes
-->
<xsl:template match="@ref"/>
<xsl:template match="templates"/>
<!-- Skip ref attributes -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

它并不完美,因为它不会删除重复的参数,但这应该是可行的(或者在此步骤中使用另一个xslt)。

答案 1 :(得分:0)

编写您可以轻松阅读的XML并应用xpath和xslt:

  1. 使用按属性区分的节点名称。 <object2>变为<object name="2"><param3>变为<param name="3">。 “ref”属性似乎捕获了这个想法,但重复了XML中已有的信息。改为推断它。
  2. 关注#1后,请使用对最终用户有意义的属性值。而不是<param2>或许<param name="pi">
  3. 这两个步骤打开了简单的xpath查询,例如/templates/object,它在编程语言中产生可迭代的结果,并且能够将数据表示为嵌套的字典/ map / struct。迭代一次设置模板,第二次重写对象参数。

    如果您的用户将直接编辑XML文件,请考虑每个文件使用一个模板或对象,并应用一些命名约定和/或目录结构。这将使系统增长时更容易识别文件。

    模板:

    <!-- templates/1.xml -->
    <template container="1" id="1">
       <param name="1">42</param>
       <param name="2">1</param>
    </object>
    

    一个对象:

    <!-- objects/1_1.xml -->
    <object container="1" id="1">
       <!--param1 "inherited" as "42"-->
       <param name="2">3.1459</param>
    </object>
    

    最后,内容管理系统通常用于解决与您描述的问题类似的问题。调查的一个好地方是Java内容库实现Apache Jackrabbit的Node Type Notation