我正在研究一个包含各种类别对象的模型,每个对象都有各种版本。我想在配置文件中将这些作为默认值提供,但也允许用户轻松自定义默认值。
这就是一般情况:
<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,然后在生成对象树之前处理生成的树。
我一直无法在其他项目中找到任何对此进行的引用 - 我甚至不确定如何搜索它。如果你这样做了,你是怎么做到的?否则,你觉得怎么样?或者你试过这个并发现它比它的价值更复杂吗?
答案 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:
<object2>
变为<object name="2">
,<param3>
变为<param name="3">
。 “ref”属性似乎捕获了这个想法,但重复了XML中已有的信息。改为推断它。 <param2>
或许<param name="pi">
。 这两个步骤打开了简单的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。