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

发布于 2024-10-08 17:27:25 字数 1340 浏览 0 评论 0原文

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

一般情况是这样的:

<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,然后处理生成的树,然后才能生成对象树。

我无法找到其他项目中对此进行的任何参考——我什至不知道如何搜索它。如果您已经这样做了,您是如何处理的?不然你觉得你会怎样?或者你尝试过这个并发现它比它的价值更复杂?

I'm working on a model with a variety of categories of objects, each with a variety of versions. I'd like to have these available as defaults in the config file, but also allow users to easily customize the defaults.

This is what the general case would look like:

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

I would like to process this next block and have the resulting object structure be identical to that created by the previous block.

<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>

That is, I would like to be able to get the same tree from reading in these two different input files. I expect to read in the XML and then process the resulting tree before being able to generate an object tree.

I've been unable to find any references to this being done in other projects--I'm not even sure how to search for it. If you've done this, how did you approach it? Otherwise, how do you think you would? Or have you tried this and found it more complicated than it's worth?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

星星的轨迹 2024-10-15 17:27:25

您可以使用 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)。

You can use an xslt like:

<?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>

It is not perfect, because it doesn't remove duplicate params, but that should be doable (or use another xslt for this step).

ま昔日黯然 2024-10-15 17:27:25

编写可以轻松读取和应用的 XML xpath 和 xslt:

  1. 使用按属性区分的节点名称。 变为 变为 。 “ref”属性似乎体现了这一想法,但重复了 XML 中已有的信息。而是推断一下。
  2. 遵循#1 后,使用对最终用户有意义的属性值。而不是 或许是

这两个步骤开启了简单的 xpath 查询,例如 /templates/object,它以编程语言生成可迭代的结果,并能够将数据表示为嵌套字典/映射/结构。迭代一次以设置模板,第二次迭代以使用对象参数覆盖。

如果您的用户将直接编辑 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 的 节点类型表示法

Write XML that you can easily read and apply xpath and xslt:

  1. Use node names differentiated by attributes. <object2> becomes <object name="2"> and <param3> becomes <param name="3">. The "ref" attribute appears to capture this idea, but repeats information already in the XML. Infer it instead.
  2. After following #1, use attribute values that have meaning to your end users. Instead of <param2> perhaps <param name="pi">.

These two steps open up easy xpath querying such as /templates/object, which produces an iterable result in a programming language, and the ability to represent your data as nested dictionary/map/struct. Iterate once to setup the templates and a second time to override with object parameters.

If your users will edit XML files directly, consider one template or object per file and apply some naming convention and/or directory structure. This will make it much easier to identify files as the system grows.

A template:

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

An object:

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

Finally, content management systems often to address similar problems as the one you describe. A good place to investigate is the Java Content Repository implementation Apache Jackrabbit's Node Type Notation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文