#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; и использовать смещения для получения того же эффекта. Так было бы проще.