2014-08-30 7 views
2

У меня есть XML со структурой,Чтение и замещающие константы в XML в процессе трансформации XSL

<root> 

    <constant name="user">johndoe</constant> 
    <constant name="server">1</constant> 

    <connection> 
    <userName>${user}</userName> 
    <port>1234</port> 
    <server>matrix.${server}.abc.com</server> 
    </connection> 

</root> 

Я извлечение информации с помощью XSLT в структуру CSV. Как заменить константные имена на их фактические значения? Если это может быть сделано в XSL, то у меня есть несколько случаев «вложенные» константы, такие как,

<constant name="a">123</constant> 
<constant name="b">10${a}</constant> 
+0

Можете ли вы использовать XSLT 2.0 или вы ограничены 1.0? –

+0

@IanRoberts да, я могу использовать XSLT 2.0 – Rnet

+0

Тогда для ваших будущих вопросов, пожалуйста, пометьте их как 'xslt-2.0' сразу. На этот раз я сделал это за тебя. –

ответ

4

Так как вы говорите в комментариях, что вы можете использовать XSLT 2.0, то это относительно просто использование analyze-string:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
       xmlns:const="urn:const" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       exclude-result-prefixes="const xs"> 

    <!-- variable holding the input tree root for use inside analyze-string --> 
    <xsl:variable name="root" select="/"/> 

    <xsl:key name="constant" match="constant" use="@name" /> 

    <!-- declare a function that you can call as const:replace(string) for any 
     string in which you want to expand out references to constants --> 
    <xsl:function name="const:replace" as="xs:string"> 
    <xsl:param name="text" as="xs:string?" /> 
    <xsl:variable name="result" as="xs:string*"> 
     <xsl:analyze-string select="$text" regex="\$\{{(.*?)\}}"> 
     <xsl:matching-substring> 
      <xsl:sequence select="key('constant', regex-group(1), $root)" /> 
     </xsl:matching-substring> 
     <xsl:non-matching-substring> 
      <xsl:sequence select="." /> 
     </xsl:non-matching-substring> 
     </xsl:analyze-string> 
    </xsl:variable> 
    <!-- analyze-string gives us a sequence of strings, join them into one 
     as the overall result of this function --> 
    <xsl:sequence select="string-join($result, '')" /> 
    </xsl:function> 

    <!-- some templates to demonstrate the function in use --> 

    <!-- drop constant elements from output --> 
    <xsl:template match="constant" /> 

    <!-- copy other elements and attributes unchanged --> 
    <xsl:template match="@*|*"> 
    <xsl:copy><xsl:apply-templates select="@*, node()" /></xsl:copy> 
    </xsl:template> 

    <!-- expand ${constant} references in text nodes --> 
    <xsl:template match="text()"> 
    <xsl:value-of select="const:replace(.)" /> 
    </xsl:template> 
</xsl:stylesheet> 

волшебное регулярное выражение \$\{(.*?)\}, но персонажи скобки должны быть удвоены, так как атрибут analyze-stringregex трактуются как attribute value template.

Handing константа в пределах констант тривиальна, сделав функцию рекурсивного

 <xsl:matching-substring> 
      <xsl:sequence select="const:replace(
        key('constant', regex-group(1), $root))" /> 
     </xsl:matching-substring> 

Несколько предостережений: это будет ввести бесконечный цикл, если есть круговые определения (a=foo${b}, b=bar${a}), а также ссылки на необъявленные константы (foo.${undeclared}.bar будет foo..bar), хотя было бы довольно легко адаптировать функцию, чтобы либо обозначить их как ошибку, либо оставить их неизменными.

+0

Еще раз спасибо! к сожалению, я столкнулся с этой ошибкой: javax.xml.transform.TransformerConfigurationException «Первый аргумент нестатической функции Java« replace »не является допустимой ссылкой на объект.» Я считаю, что это может быть связано с ограничениями процессора в JDK7, и мне может потребоваться пакет внешнего процессора с моим кодом, что вы предложите? – Rnet

+2

@Rnet, как я намекнул в своем последнем комментарии к предыдущему вопросу, по умолчанию XSLT-процессор за «javax.xml.transform» в JDK поддерживает только XSLT 1.0. Если вы хотите использовать 2.0, вам необходимо использовать Saxon 9. Для базовой обработки, отличной от схемы, версия «HE» с открытым исходным кодом из [SourceForge] (http://saxon.sourceforge.net) достаточна, если вам нужно более продвинутые функции коммерческих изданий можно приобрести на http://saxonica.com –

+0

ах, извините, я, должно быть, пропустил это. Спасибо за ваше время и помощь! – Rnet

Смежные вопросы