XSLT:如何仅根据值为节点生成唯一 ID [英] XSLT: How to generate unique id for node based on value only

查看:29
本文介绍了XSLT:如何仅根据值为节点生成唯一 ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个源 XML,其中包含可能具有相同值的地址元素(请注意 Contact/id=1 和 Contact/id=3 具有相同的地址:

I have a source XML that contains address elements which could have the same values (please note that Contact/id=1 and Contact/id=3 have the same address:

<?xml version="1.0" encoding="utf-8"?>
<Contacts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Contact>
        <id>1</id>
        <Address>
            <City City="Wien" />
            <Postcode Postcode="LSP-123" />
        </Address>
    </Contact>
    <Contact>
        <id>2</id>        
        <Address>
            <City City="Toronto" />
            <Postcode Postcode="LKT-947" />
        </Address>
    </Contact>
    <Contact>
        <id>3</id>        
        <Address>
            <City City="Wien" />
            <Postcode Postcode="LSP-123" />
        </Address>
    </Contact>
</Contacts> 

所需的 XSLT 1.0 输出:

Desired output with XSLT 1.0:

<?xml version="1.0" encoding="utf-8"?>
<Contacts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Contact>
        <id>1</id>
        <Address>SomeId_1</Address>
    </Contact>
    <Contact>
        <id>2</id>        
        <Address>SomeId_2</Address>
    </Contact>
    <Contact>
        <id>3</id>        
        <Address>SomeId_1</Address>
    </Contact>
</Contacts>

当我使用函数 generate-id(Address) 时,我为 Contact 1 和 Contact 3 中的地址获得了不同的 id.还有什么其他方法可以仅根据节点的值为节点生成唯一 id?

When I used function generate-id(Address) I got different id for addresses in Contact 1 and Contact 3. What other way to generate unique id for node based on its value only?

感谢您的帮助.

推荐答案

我建议建立一个键值作为查找表,然后从查找表的第一个条目开始定位唯一编号:

I would advise building a key of values as a lookup table and then just orienting from the first entry of the lookup table for the unique number:

t:\ftemp>type ivan.xml 
<?xml version="1.0" encoding="utf-8"?>
<Contacts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Contact>
        <id>1</id>
        <Address>
            <City City="Wien" />
            <Postcode Postcode="LSP-123" />
        </Address>
    </Contact>
    <Contact>
        <id>2</id>        
        <Address>
            <City City="Toronto" />
            <Postcode Postcode="LKT-947" />
        </Address>
    </Contact>
    <Contact>
        <id>3</id>        
        <Address>
            <City City="Wien" />
            <Postcode Postcode="LSP-123" />
        </Address>
    </Contact>
</Contacts> 
t:\ftemp>call xslt ivan.xml ivan.xsl 
<?xml version="1.0" encoding="utf-8"?><Contacts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Contact>
        <id>1</id>
        <Address>SomeId_1</Address>
    </Contact>
    <Contact>
        <id>2</id>        
        <Address>SomeId_2</Address>
    </Contact>
    <Contact>
        <id>3</id>        
        <Address>SomeId_1</Address>
    </Contact>
</Contacts>
t:\ftemp>type ivan.xsl 
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

<xsl:key name="city-pc-pair" match="Address"
         use="concat(City/@City,'&#xd;',Postcode/@PostCode)"/>

<xsl:template match="Address">
  <xsl:for-each select="key('city-pc-pair',
                            concat(City/@City,'&#xd;',Postcode/@PostCode))[1]">
    <Address>SomeId_<xsl:number level="any"/></Address>
  </xsl:for-each>
</xsl:template>

<xsl:template match="@*|node()"><!--identity for all other nodes-->
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rem Done! 

至于我使用的串联,我告诉我的学生使用回车作为字段分隔符的技术可以将意外值冲突的可能性降低到无限小,因为 XML 中硬回车很少内容(作为行尾序列一部分的回车被标准化为换行符,因此不会出现在数据中).

As for the concatenation that I'm using, I tell my students the technique of using a carriage return as a field delimiter reduces the likelihood of an unintended value collision to an infinitesimal size since there are very few hard carriage returns in XML content (those carriage returns that are parts of end-of-line sequences are normalized to a line-feed and so do not appear in the data).

编辑添加以下实体技术,可以改进维护,因为它将查找表达式集中到样式表中的单个声明中,以免意外地在样式表的两个不同部分中编写不同:

Edited to add the following entity technique that may improve maintenance since it focuses the lookup expression to a single declaration in the stylesheet, so as not to be accidentally written differently in two different parts of the stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet
[
<!ENTITY lookup "concat(City/@City,'&#xd;',Postcode/@PostCode)">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

<xsl:key name="city-pc-pair" match="Address" use="&lookup;"/>

<xsl:template match="Address">
  <xsl:for-each select="key('city-pc-pair',&lookup;)[1]">
    <Address>SomeId_<xsl:number level="any"/></Address>
  </xsl:for-each>
</xsl:template>

<xsl:template match="@*|node()"><!--identity for all other nodes-->
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

这篇关于XSLT:如何仅根据值为节点生成唯一 ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆