如何为父子孙元素分配一个唯一的 id?

How to assign a unique id to the Parent, child and grandchild element?

我是 xslt 的新手,如果有人能帮助我解决这个问题,那将非常有帮助。 我有一个 XML 文档,看起来像这样,

    <ParentElement>
     <ChildElement name = "xxx" place = "yyy">
      <GrandChildElement parameter1 = "a" parameter2 = "b">
      </GrandchildElement>
        <GrandChildElement parameter1 = "c" parameter2 = "d">
      </GrandchildElement>
     </ChildElement>
     <ChildElement name = "xxx" place = "yyy">
      <GrandChildElement parameter1 = "a" parameter2 = "x">  
    </GrandchildElement>
        <GrandChildElement parameter1 = "c" parameter2 = "y">
      </GrandchildElement>
     </ChildElement>
    </ParentElement>
    

我想为每个子元素和每个孙元素分配一个唯一的 ID。我想要的输出应该是这样的,

    <ParentElement>
    <ChildElement>
           <Child_ID>100</Child_ID>
            <Name></Name>
                 <GrandChild>
                    <id>200</id>
                    <Label></Label>
                 </GrandChild>
                 <GrandChild>
                    <id>201</id>
                    <Label></Label>
                 </GrandChild>
                 <GrandChild>
                    <id>202</id>
                    <Label></Label>
                 </GrandChild>
      </ChildElement>
    
    <ChildElement>
            <Child_ID>101</Child_ID>
            <Name></Name>
                 <GrandChild>
                    <id>203</id>
                    <Label></Label>
                 </GrandChild>
                 <GrandChild>
                    <id>204</id>
                    <Label></Label>
                 </GrandChild>
      </ChildElement>
    </ParentElement>
    

我使用它为成功的子元素创建了 id。

            <xsl:for-each select="ChildElement">
            <xsl:variable name="i" select="1" />
            <xsl:variable name="j" select="$i + position()"/>
    
                <xsl:element name = "ChildElement">
                <xsl:element name = "Id">DT-<xsl:value-of select="200 + $j"/></xsl:element>
            </xsl:for-each>
    

如何为每个孙子获得不同的 ID?

XSLT 具有为输入中的每个节点生成唯一 ID 的内置函数 XML。考虑以下示例:

XML

<ParentElement>
    <ChildElement name = "xxx" place = "yyy">
        <GrandChildElement parameter1 = "a" parameter2 = "b"/>
        <GrandChildElement parameter1 = "c" parameter2 = "d"/>
    </ChildElement>
    <ChildElement name = "xxx" place = "yyy">
        <GrandChildElement parameter1 = "a" parameter2 = "x"/>  
        <GrandChildElement parameter1 = "c" parameter2 = "y"/>
    </ChildElement>
</ParentElement>

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="ParentElement">
    <xsl:copy>
        <xsl:for-each select="ChildElement">
            <xsl:copy>
                <Child_ID>
                    <xsl:value-of select="generate-id()"/>
                </Child_ID>
                <xsl:for-each select="GrandChildElement">
                    <GrandChild>
                        <id>
                            <xsl:value-of select="generate-id()"/>
                        </id>
                    </GrandChild>
                </xsl:for-each>
            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

确切的结果因处理器而异。例如,libxslt 可能 return 结果如下:

<?xml version="1.0" encoding="UTF-8"?>
<ParentElement>
  <ChildElement>
    <Child_ID>idm49868912656</Child_ID>
    <GrandChild>
      <id>idm49868912048</id>
    </GrandChild>
    <GrandChild>
      <id>idm49868911344</id>
    </GrandChild>
  </ChildElement>
  <ChildElement>
    <Child_ID>idm49868910448</Child_ID>
    <GrandChild>
      <id>idm49868909744</id>
    </GrandChild>
    <GrandChild>
      <id>idm49868909008</id>
    </GrandChild>
  </ChildElement>
</ParentElement>

Xalan 将产生如下结果:

<?xml version="1.0" encoding="UTF-8"?><ParentElement>
<ChildElement>
<Child_ID>N10004</Child_ID>
<GrandChild>
<id>N10008</id>
</GrandChild>
<GrandChild>
<id>N1000C</id>
</GrandChild>
</ChildElement>
<ChildElement>
<Child_ID>N10011</Child_ID>
<GrandChild>
<id>N10015</id>
</GrandChild>
<GrandChild>
<id>N10019</id>
</GrandChild>
</ChildElement>
</ParentElement>

因此,如果您正在寻找您在输入中显示的模式 XML,这可能是一种方法。您必须考虑当您拥有超过 100 个 ChildElement 元素时会发生什么。只是玩你的抵消。如果你不想在你的 id 中使用字母,这种方法可能会有用。或者您正在处理多个 XML。只需将参数传递给您的 XSLT 文件和您的唯一起始偏移量。

<xsl:stylesheet version="1.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxml="urn:schemas-microsoft-com:xslt">
      <xsl:output indent="yes"/>

    <xsl:variable name="childIDs">
     <xsl:for-each select="//ChildElement">
        <xsl:element name="element">
          <xsl:element name="id">
            <xsl:value-of select="generate-id(.)"/>
          </xsl:element>    
          <xsl:element name="outid">
            <xsl:value-of select="position() + 100"/>
          </xsl:element>
        </xsl:element>
      </xsl:for-each>
    </xsl:variable>

    <!-- For 1.0 use your own prefix here.  It may not be msxml.  -->
    <xsl:variable name="childIDList" select="msxml:node-set($childIDs)"/>

    <xsl:variable name="grandchildIDs">
      <xsl:for-each select="//GrandChildElement">
        <xsl:element name="element">
          <xsl:element name="id">
            <xsl:value-of select="generate-id(.)"/>
          </xsl:element>    
          <xsl:element name="outid">
            <xsl:value-of select="position() + 200"/>
          </xsl:element>
        </xsl:element>
      </xsl:for-each>
    </xsl:variable>

    <!-- For 1.0 use your own prefix here.  It may not be msxml.  -->
    <xsl:variable name="grandchildIDList" select="msxml:node-set($grandchildIDs)"/>

    <xsl:template match="ChildElement">
      <xsl:variable name="id" select="generate-id(.)"/>
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:element name="Child_ID">
          <xsl:value-of select="$childIDList/element[id = $id]/outid"/>
        </xsl:element>
        <xsl:apply-templates select="node()"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="GrandChildElement">
      <xsl:variable name="id" select="generate-id(.)"/>
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:element name="id">
          <xsl:value-of select="$grandchildIDList/element[id = $id]/outid"/>
        </xsl:element>
        <xsl:apply-templates select="node()"/>
      </xsl:copy>
    </xsl:template>

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

</xsl:stylesheet>