2

我有一组文档隐式定义了第二组对象的允许字段,这些对象必须转换为第三组文档(要使用的“规则”文档取决于要转换的文件的内容),例如

<!-- One example rules document --> 
<document object="obj1_rules">
<field name="A"/>
<field name="B"/>
<field name="C"/>
</document>

<!-- Document to be tranformed based upon obj1_rules--> 
<document object="obj1">
<field name="A"/>
<field name="B"/>
<field name="C"/>
<field name="D"/>
<field name="E"/>
</document>

<!-- Desired result--> 
<document object="obj1">
<newfield name="A"/>
<newfield name="B"/>
<newfield name="C"/>
</document>

是否可以使用 xslt 进行这种转换?

我看到“XSLT 无法在运行时构造 XPath 表达式(例如变量引用)”。 所以我不走运,或者我只是错误地看待这个问题?谢谢!

4

3 回答 3

2

这是一个简单的解决方案

这种转变

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
<!--                                                   -->  
    <xsl:variable name="vrtfRules">
        <document object="obj1_rules">
            <field name="A"/>
            <field name="B"/>
            <field name="C"/>
        </document>
    </xsl:variable>
<!--                                                   -->  
    <xsl:variable name="vRules" select=
     "document('')/*/xsl:variable
                   [@name = 'vrtfRules']
                     /*
     "/>
<!--                                                   -->  
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
<!--                                                   -->  
    <xsl:template match="field">
      <xsl:if test="@name = $vRules/*/@name">
        <newfield>
          <xsl:apply-templates select="node()|@*"/>
        </newfield>
      </xsl:if>
    </xsl:template>
</xsl:stylesheet>

当应用于原始提供的源 XML 文档时:

<document object="obj1">
    <field name="A"/>
    <field name="B"/>
    <field name="C"/>
    <field name="D"/>
    <field name="E"/>
</document>

产生所需的结果:

<document object="obj1">
   <newfield name="A"/>
   <newfield name="B"/>
   <newfield name="C"/>
</document>

请注意,“规则文档”在样式表中只是为了紧凑。单独文件时,只document()需要根据实际使用的功能进行调整href

于 2009-03-15T15:20:13.147 回答
1

也许我过于简单化了,但是为什么您的“规则文档”不能简单地成为 XSLT 有什么原因吗?

于 2009-03-15T04:53:58.017 回答
1

好吧,我明白为什么您希望在简单的 xml 文件中而不是在成熟的 xsl 样式表中包含规则,但您只是跳过了一个步骤。

您需要制作一个 xsl 样式表,它将您的 xml 规则文档转换为一个 xsl 样式表,然后您将其应用于您的源 xml。

诀窍在于命名空间,而不是被应用的 xsl 规则和生成的 xsl 规则的混合混淆。

    <?xml 版本="1.0" ?>
    <xsl:样式表
        xmlns="YOUR_NAMESPACE_HERE"
        xmlns:output="http://www.w3.org/1999/XSL/Transform"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        版本="2.0">

        <xsl:输出
            方法="xml"
            缩进=“是”
            媒体类型="文本/xsl" />

        <xsl:模板匹配="/">
            <输出:样式表版本=“2.0”>
                <xsl:应用模板 />
            </输出:样式表>
        </xsl:模板>

        <xsl:template match="文档[@object]">
            <输出:模板匹配="文档[@object='{@object}']">
                <输出:复制>
                    <xsl:应用模板 />
                </输出:复制>
            </输出:模板>
        </xsl:模板>

        <xsl:template match="字段[@name]">
            <输出:if test="field[@name='{@name}']">
                <output:copy-of select="field[@name='{@name}']" />
            </输出:如果>
        </xsl:模板>

    </xsl:样式表>

我假设您会在规则和文档本身中使用相同的文档对象属性(这在 imo 中要简单得多)。

因此,您通过上面的样式表运行您的规则文档。结果是一个新的 xsl 样式表,它完全按照您在 xml 规则文档中的描述进行操作。然后,您将这个生成的样式表应用到您的源文档中,您应该会得到您期望的结果。

于 2009-03-15T05:33:26.863 回答