为同一个XSL文件生成两个不同的输出?

时间:2011-07-20 15:08:40

标签: javascript xml xslt

这是我的XML文件,如果我运行XSLt文件,我将在Eclipse XSL Transformation中以相同的顺序获得相同的输出。 即使向我的xml文件添加新记录并运行XSL文件,<xsl:value-of select="generate-id(.)"/>也会为新记录创建唯一ID。

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

<CONTACT>
<Customer-ID>N65539</Customer-ID>
<FirstName>Ben</FirstName>
<LastName>Foden</LastName>
<email></email>
<address></address>
<state>AZ</state>
<country>US</country>
</CONTACT>

<CONTACT>
<Customer-ID>N65539</Customer-ID>
<FirstName>Nimal</FirstName>
<LastName>Anup</LastName>
<email>nimal.anup@gmail.com</email>
<address></address>
<state>TN</state>
<country>IN</country>
</CONTACT>


<CONTACTS>

这是我更新的XSLT文件:

  <?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />

<!--Identity template to copy content forward-->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

    <xsl:template match="CONTACT">
<xsl:copy>
    <Customer-ID>
    <xsl:apply-templates select="node()" mode="generate-id"/>
    </Customer-ID>

    <FirstName>
    <xsl:value-of select="FirstName"/> 
    </FirstName>

    <LastName>
    <xsl:value-of select="LastName"/> 
    </LastName>

    <email>
    <xsl:value-of select="email"/> 
    </email>

    <address>
    <xsl:value-of select="address"/> 
    </address>

    <state>
    <xsl:value-of select="state"/> 
    </state>

    <country>
    <xsl:value-of select="country"/> 
    </country>

</xsl:copy>
    </xsl:template>

    <xsl:template match="node()" mode="generate-id">
    <xsl:text>N</xsl:text>
    <xsl:number level="single" count="node()" format="100"/>        
    </xsl:template>

</xsl:stylesheet>

然后我在XUL中为XSLT处理器函数使用了相同的XSLT文件,我得到了不同类型的ID和输出。 它会继续为旧记录和新记录生成新ID如果我在XML文件中添加新记录。

如何仅为新记录生成新ID?如何将输入文件的XML模板与我的XML输出文件相同。

这是我得到的输出:

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

<CONTACT><Customer-ID>id0x03e4a620</Customer-ID><FirstName>Ben</FirstName><LastName>Foden</LastName><email></email><address></address><state>AZ</state><country>US</country></CONTACT>

<CONTACT><Customer-ID>id0x03e4ad80</Customer-ID><FirstName>Nimal</FirstName><LastName>Anup</LastName><email>nimal.anup@gmail.com</email><address></address><state>TN</state><country>IN</country></CONTACT>

<CONTACTS>

这是我调用XSLT文件的Javascript:脚本在保存XML文件后调用此函数。新记录的更新方式与输入xml文件中提到的相同。

function process()
{

var src = readFile("c:\\idgenerator.xsl");
var parsed = (new DOMParser()).parseFromString(src, "text/xml");
var stylesheet = parsed.documentElement;

var processor = new XSLTProcessor();
processor.importStylesheet(stylesheet );

objXMLDoc = processor.transformToDocument(objXMLDoc);

var serializer = new XMLSerializer();
var prettyString = serializer.serializeToString(objXMLDoc);

saveFile(prettyString, "C:\\mercredi.xml");

} 

非常感谢。

3 个答案:

答案 0 :(得分:3)

如果generate-id()在不同的运行中产生可重复的结果,那么这是您的XSLT处理器设计的意外,而不是您可以依赖的行为。

答案 1 :(得分:2)

我不知道Eclipse使用的是什么XSLT处理器。至少在某些扩展程序中,您可以配置处理器,例如到Xalan或Saxon。 Mozilla / XUL至少在默认情况下使用Transformiix。我在某处读到可以使用Saxon。 不同的XSLT处理器之间肯定存在差异。

generate-id()的规范没有说明生成的ID应该是什么样的;只是他们“必须由ASCII字母数字字符组成,并且必须以字母字符开头”。

如果您希望XSLT-under-XUL生成与Eclipse相同类型的ID,那么您有几个选项。

1)您可以尝试让XUL使用Eclipse使用的XSLT处理器。我不知道这是否可能。

2)实施您自己的自定义模板以生成ID。

使用后者,如果你有一些基于它们的稳定数据,那么模仿你在Eclipse中获得的ID的风格并使它们在多个运行和不同的XSLT处理器中保持稳定并不难。

例如,如果您的记录顺序始终稳定(旧记录永远不会被删除,交换或替换),那么您可以使用这样的模板来生成ID:

<xsl:template match="node()" mode="generate-id">
    <xsl:text>N</xsl:text>
    <xsl:number level="any" count="node()" format="00001"/>        
</xsl:template>

如果订单不稳定,但名字+姓氏既稳定又独特,您可以使用

<xsl:template match="node()" mode="generate-id">
   <xsl:value-of select="concat(FirstName, LastName)" />
</xsl:template>

答案 2 :(得分:0)

generate-id()以这种方式工作,您可以在使用generate-id()之前验证联系人中是否有Customer-ID ...

<xsl:if test="./Customer-Id=''"> <!-- if the new contact comes with this empty -->
    <Customer-ID>
        <xsl:value-of select="generate-id(.)"/> 
    </Customer-ID>
<xsl:if>
<xsl:if test="not(./Customer-Id='')"> <!-- if the contact comes with Customer-Id -->
    <Customer-ID>
        <xsl:value-of select="Customer-Id"/> 
    </Customer-ID>
<xsl:if>