как создать уникальную строку - PullRequest
6 голосов
/ 22 декабря 2010

Я хочу преобразовать документ XML в HTML.Некоторые элементы XML имеют ссылки на другие документы, такие как:

<link href="1.html">

В выводе HTML я хочу получить:

<a href="1.html&no_cache={unique_id}">

Как я могу сгенерировать этот уникальный довольно большой идентификатор?

Ответы [ 4 ]

5 голосов
/ 22 декабря 2010

Для начала я предполагаю, что по неизвестной причине вы не можете использовать абсолютный URL в link в качестве требуемого UID - это самое простое и естественное решение.

Если мое предположение верно, то:

Это простая задача для XSLT .

Поскольку OP хочет, чтобы сгенерированные идентификаторы были одинаковыми, когда преобразование выполняется несколько раз, использование generate-id() нецелесообразно.

Вот один простой способ получения стабильных идентификаторов :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="link[@href]">
  <xsl:variable name="vUid">
    <xsl:number level="any" count="link[@href]"/>
  </xsl:variable>
   <a href="{@href}&amp;no_cache={{{$vUid}}}"/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к следующему документу XML (независимо от того, сколько раз):

<t>
 <link href="1.html"/>
 <a>
   <link href="2.html"/>
  <b>
    <link href="3.html"/>
    <c>
     <link href="4.html"/>
    </c>
    <link href="5.html"/>
  </b>
  <link href="6.html"/>
  <d>
   <link href="7.html"/>
  </d>
 </a>
 <link href="8.html"/>
 <e>
  <link href="9.html"/>
 </e>
 <link href="10.html"/>
</t>

желаемый, один и тот же, правильный результат выдается каждый раз :

<t>
   <a href="1.html&amp;no_cache={1}"/>
   <a>
      <a href="2.html&amp;no_cache={2}"/>
      <b>
         <a href="3.html&amp;no_cache={3}"/>
         <c>
            <a href="4.html&amp;no_cache={4}"/>
         </c>
         <a href="5.html&amp;no_cache={5}"/>
      </b>
      <a href="6.html&amp;no_cache={6}"/>
      <d>
         <a href="7.html&amp;no_cache={7}"/>
      </d>
   </a>
   <a href="8.html&amp;no_cache={8}"/>
   <e>
      <a href="9.html&amp;no_cache={9}"/>
   </e>
   <a href="10.html&amp;no_cache={10}"/>
</t>

Примечание : использование <xsl:number> для получения идентификатора.

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

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kHrefByVal" match="link/@href" use="."/>

 <xsl:variable name="vUniqHrefs" select=
  "//link/@href
       [generate-id()
       =
        generate-id(key('kHrefByVal',.)[1])
       ]
  "/>


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

 <xsl:template match="link[@href]">
  <xsl:variable name="vthisHref" select="@href"/>

  <xsl:variable name="vUid">
   <xsl:for-each select="$vUniqHrefs">
    <xsl:if test=". = $vthisHref">
     <xsl:value-of select="position()"/>
    </xsl:if>
   </xsl:for-each>
  </xsl:variable>
   <a href="{@href}&amp;no_cache={{{$vUid}}}"/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к следующему документу XML :

<t>
 <link href="1.html"/>
 <a>
   <link href="2.html"/>
  <b>
    <link href="1.html"/>
    <c>
     <link href="3.html"/>
    </c>
    <link href="2.html"/>
  </b>
  <link href="1.html"/>
  <d>
   <link href="3.html"/>
  </d>
 </a>
 <link href="4.html"/>
 <e>
  <link href="2.html"/>
 </e>
 <link href="4.html"/>
</t>

желаемый, правильный результат получается :

<t>
   <a href="1.html&amp;no_cache={1}"/>
   <a>
      <a href="2.html&amp;no_cache={2}"/>
      <b>
         <a href="1.html&amp;no_cache={1}"/>
         <c>
            <a href="3.html&amp;no_cache={3}"/>
         </c>
         <a href="2.html&amp;no_cache={2}"/>
      </b>
      <a href="1.html&amp;no_cache={1}"/>
      <d>
         <a href="3.html&amp;no_cache={3}"/>
      </d>
   </a>
   <a href="4.html&amp;no_cache={4}"/>
   <e>
      <a href="2.html&amp;no_cache={2}"/>
   </e>
   <a href="4.html&amp;no_cache={4}"/>
</t>
3 голосов
/ 22 декабря 2010

try generate-id ().

<xsl:value-of select="generate-id(.)"/>

вот дальнейшее объяснение: http://www.w3schools.com/XSL/func_generateid.asp

2 голосов
/ 22 декабря 2010

Это невозможно с чистым XSLT, но некоторые альтернативные варианты могут быть:

  1. Добавьте расширение пространства имен, чтобы вы могли обращаться к не-XSLT-коду: <a href="1.html&no_cache={myns:unique_id()}">. Это даст вам результат, к которому вы стремитесь, но зависит от поддержки со стороны платформы, которую вы используете для выполнения преобразования.
  2. Используйте JavaScript, чтобы добавить уникальный идентификатор в ссылки на клиенте. Работает только в том случае, если на вашем клиенте включен JavaScript, но может быть приемлемым компромиссом, если вы знаете, что так оно и будет.
  3. Установите заголовки HTTP на своих страницах, чтобы предотвратить кэширование. Возможно, это лучший вариант с семантической точки зрения, и вы не рискуете, чтобы поисковые системы неоднократно сканировали вашу страницу с каждым уникальным идентификатором.
0 голосов
/ 22 декабря 2010

XSLT - это функциональные языки, которые означают, что для данного ввода он всегда будет производить один и тот же вывод, поэтому по определению метод guid или любой другой генератор случайных чисел не будет частью спецификации проекта. Лучше всего, если вы привязаны к клиенту, использовать метод, связанный со временем, как часть псевдослучайного начального числа для generate-id, однако, поскольку ваша цель, по-видимому, заключается в сильном затухании, вам следует отказаться от этого и сосредоточиться на применении заголовки анти-кэша для ресурсов, которые вы пытаетесь защитить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...