Как присвоить уникальный идентификатор родительскому, дочернему и внучатому элементу?

#xslt-1.0

Вопрос:

Я новичок в xslt, и было бы очень полезно, если бы кто-нибудь мог помочь мне с этой проблемой. У меня есть XML-документ, который выглядит примерно так,

 lt;ParentElementgt;  lt;ChildElement name = "xxx" place = "yyy"gt;  lt;GrandChildElement parameter1 = "a" parameter2 = "b"gt;  lt;/GrandchildElementgt;  lt;GrandChildElement parameter1 = "c" parameter2 = "d"gt;  lt;/GrandchildElementgt;  lt;/ChildElementgt;  lt;ChildElement name = "xxx" place = "yyy"gt;  lt;GrandChildElement parameter1 = "a" parameter2 = "x"gt;   lt;/GrandchildElementgt;  lt;GrandChildElement parameter1 = "c" parameter2 = "y"gt;  lt;/GrandchildElementgt;  lt;/ChildElementgt;  lt;/ParentElementgt;    

Я хочу присвоить уникальный идентификатор каждому дочернему элементу и каждому внуку. Результат, который я хочу, должен быть примерно таким,

 lt;ParentElementgt;  lt;ChildElementgt;  lt;Child_IDgt;100lt;/Child_IDgt;  lt;Namegt;lt;/Namegt;  lt;GrandChildgt;  lt;idgt;200lt;/idgt;  lt;Labelgt;lt;/Labelgt;  lt;/GrandChildgt;  lt;GrandChildgt;  lt;idgt;201lt;/idgt;  lt;Labelgt;lt;/Labelgt;  lt;/GrandChildgt;  lt;GrandChildgt;  lt;idgt;202lt;/idgt;  lt;Labelgt;lt;/Labelgt;  lt;/GrandChildgt;  lt;/ChildElementgt;    lt;ChildElementgt;  lt;Child_IDgt;101lt;/Child_IDgt;  lt;Namegt;lt;/Namegt;  lt;GrandChildgt;  lt;idgt;203lt;/idgt;  lt;Labelgt;lt;/Labelgt;  lt;/GrandChildgt;  lt;GrandChildgt;  lt;idgt;204lt;/idgt;  lt;Labelgt;lt;/Labelgt;  lt;/GrandChildgt;  lt;/ChildElementgt;  lt;/ParentElementgt;    

Я использовал что — то подобное для создания идентификаторов для дочерних элементов, что было успешным.

 lt;xsl:for-each select="ChildElement"gt;  lt;xsl:variable name="i" select="1" /gt;  lt;xsl:variable name="j" select="$i   position()"/gt;    lt;xsl:element name = "ChildElement"gt;  lt;xsl:element name = "Id"gt;DT-lt;xsl:value-of select="200   $j"/gt;lt;/xsl:elementgt;  lt;/xsl:for-eachgt;    

что я могу сделать, чтобы получить разные удостоверения личности для каждого внука?

Комментарии:

1. Вам нужны последовательные числа, такие как 100, 101… и 200, 201 … или подойдет любая уникальная строка?

2. подойдет любой уникальный номер

Ответ №1:

XSLT имеет встроенную функцию для создания уникального идентификатора для каждого узла во входном XML. Рассмотрим следующий пример:

XML

 lt;ParentElementgt;  lt;ChildElement name = "xxx" place = "yyy"gt;  lt;GrandChildElement parameter1 = "a" parameter2 = "b"/gt;  lt;GrandChildElement parameter1 = "c" parameter2 = "d"/gt;  lt;/ChildElementgt;  lt;ChildElement name = "xxx" place = "yyy"gt;  lt;GrandChildElement parameter1 = "a" parameter2 = "x"/gt;   lt;GrandChildElement parameter1 = "c" parameter2 = "y"/gt;  lt;/ChildElementgt; lt;/ParentElementgt;  

XSLT 1.0

 lt;xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"gt; lt;xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/gt;  lt;xsl:template match="ParentElement"gt;  lt;xsl:copygt;  lt;xsl:for-each select="ChildElement"gt;  lt;xsl:copygt;  lt;Child_IDgt;  lt;xsl:value-of select="generate-id()"/gt;  lt;/Child_IDgt;  lt;xsl:for-each select="GrandChildElement"gt;  lt;GrandChildgt;  lt;idgt;  lt;xsl:value-of select="generate-id()"/gt;  lt;/idgt;  lt;/GrandChildgt;  lt;/xsl:for-eachgt;  lt;/xsl:copygt;  lt;/xsl:for-eachgt;  lt;/xsl:copygt; lt;/xsl:templategt;  lt;/xsl:stylesheetgt;  

Точный результат варьируется от одного процессора к другому. Например, libxslt может возвращать результат, подобный:

 lt;?xml version="1.0" encoding="UTF-8"?gt; lt;ParentElementgt;  lt;ChildElementgt;  lt;Child_IDgt;idm49868912656lt;/Child_IDgt;  lt;GrandChildgt;  lt;idgt;idm49868912048lt;/idgt;  lt;/GrandChildgt;  lt;GrandChildgt;  lt;idgt;idm49868911344lt;/idgt;  lt;/GrandChildgt;  lt;/ChildElementgt;  lt;ChildElementgt;  lt;Child_IDgt;idm49868910448lt;/Child_IDgt;  lt;GrandChildgt;  lt;idgt;idm49868909744lt;/idgt;  lt;/GrandChildgt;  lt;GrandChildgt;  lt;idgt;idm49868909008lt;/idgt;  lt;/GrandChildgt;  lt;/ChildElementgt; lt;/ParentElementgt;  

в то время Xalan как приведет к такому результату, как:

 lt;?xml version="1.0" encoding="UTF-8"?gt;lt;ParentElementgt; lt;ChildElementgt; lt;Child_IDgt;N10004lt;/Child_IDgt; lt;GrandChildgt; lt;idgt;N10008lt;/idgt; lt;/GrandChildgt; lt;GrandChildgt; lt;idgt;N1000Clt;/idgt; lt;/GrandChildgt; lt;/ChildElementgt; lt;ChildElementgt; lt;Child_IDgt;N10011lt;/Child_IDgt; lt;GrandChildgt; lt;idgt;N10015lt;/idgt; lt;/GrandChildgt; lt;GrandChildgt; lt;idgt;N10019lt;/idgt; lt;/GrandChildgt; lt;/ChildElementgt; lt;/ParentElementgt;  

Комментарии:

1. Большое вам спасибо, Майкл, за подробное объяснение. 🙂 Я хочу, чтобы идентификаторы были номерами, например, от 100 до 300 (или тест lt;Child_IDgt;: 100lt;Child_IDgt;lt;/Child_IDgt;). Я использую процессор msxsl.

2. Ну, я спросил, прежде чем опубликовать это. Тебе следовало сказать «нет».

3. Извините, что не ясно это сформулировал..

Ответ №2:

Итак, если вы ищете шаблон, который вы показали во входном XML, это может быть одним из подходов. Вы должны учитывать, что происходит, когда у вас более 100 дочерних элементов. Просто поиграй со своими смещениями. Этот подход может быть полезен, если вы не хотите, чтобы в вашем удостоверении личности были буквы. Или вы имеете дело с несколькими XML. Просто передайте параметр в свой файл XSLT с вашим уникальным начальным смещением.

 lt;xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:msxml="urn:schemas-microsoft-com:xslt"gt;  lt;xsl:output indent="yes"/gt;   lt;xsl:variable name="childIDs"gt;  lt;xsl:for-each select="//ChildElement"gt;  lt;xsl:element name="element"gt;  lt;xsl:element name="id"gt;  lt;xsl:value-of select="generate-id(.)"/gt;  lt;/xsl:elementgt;   lt;xsl:element name="outid"gt;  lt;xsl:value-of select="position()   100"/gt;  lt;/xsl:elementgt;  lt;/xsl:elementgt;  lt;/xsl:for-eachgt;  lt;/xsl:variablegt;   lt;!-- For 1.0 use your own prefix here. It may not be msxml. --gt;  lt;xsl:variable name="childIDList" select="msxml:node-set($childIDs)"/gt;   lt;xsl:variable name="grandchildIDs"gt;  lt;xsl:for-each select="//GrandChildElement"gt;  lt;xsl:element name="element"gt;  lt;xsl:element name="id"gt;  lt;xsl:value-of select="generate-id(.)"/gt;  lt;/xsl:elementgt;   lt;xsl:element name="outid"gt;  lt;xsl:value-of select="position()   200"/gt;  lt;/xsl:elementgt;  lt;/xsl:elementgt;  lt;/xsl:for-eachgt;  lt;/xsl:variablegt;   lt;!-- For 1.0 use your own prefix here. It may not be msxml. --gt;  lt;xsl:variable name="grandchildIDList" select="msxml:node-set($grandchildIDs)"/gt;   lt;xsl:template match="ChildElement"gt;  lt;xsl:variable name="id" select="generate-id(.)"/gt;  lt;xsl:copygt;  lt;xsl:apply-templates select="@*"/gt;  lt;xsl:element name="Child_ID"gt;  lt;xsl:value-of select="$childIDList/element[id = $id]/outid"/gt;  lt;/xsl:elementgt;  lt;xsl:apply-templates select="node()"/gt;  lt;/xsl:copygt;  lt;/xsl:templategt;   lt;xsl:template match="GrandChildElement"gt;  lt;xsl:variable name="id" select="generate-id(.)"/gt;  lt;xsl:copygt;  lt;xsl:apply-templates select="@*"/gt;  lt;xsl:element name="id"gt;  lt;xsl:value-of select="$grandchildIDList/element[id = $id]/outid"/gt;  lt;/xsl:elementgt;  lt;xsl:apply-templates select="node()"/gt;  lt;/xsl:copygt;  lt;/xsl:templategt;   lt;xsl:template match="node()|@*"gt;  lt;xsl:copygt;  lt;xsl:apply-templates select="node()|@*"/gt;  lt;/xsl:copygt;  lt;/xsl:templategt;  lt;/xsl:stylesheetgt;  

Комментарии:

1. Вау, это БОЛЬШАЯ работа. Я считаю, что большей части этого можно было бы избежать, используя встроенную функциональность xsl:number .

2. Да, вы можете использовать lt;xsl:количество номеров=»Дочерний элемент»/gt; и lt;xsl:количество номеров=»Дочерний элемент»/gt;lt;xsl:количество номеров=»Внучатый элемент»/gt; и использовать смещения для получения того же эффекта. Так было бы проще.