1

XMLドキュメントの一部のテキストノードを外部ファイルのelements属性と照合して、それらを置き換え/変更しようとしています。

これが私のXMLファイルです。

<root>
    <level_1>
        <item_1>xxxxx</item_1>
        <item_2>yyyyy</item_2>
        <item_3>zzzzz</item_3>
    </level_1>
</root>

XSLTコード:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:functx="http://www.functx.com">
    <xsl:param name="additionalInfoPath"/>
    <xsl:output indent="yes" />
    <xsl:function name="functx:contains-any-of" as="xs:boolean" 
              xmlns:functx="http://www.functx.com" >
  <xsl:param name="arg" as="xs:string?"/> 
  <xsl:param name="searchStrings" as="xs:string*"/> 

  <xsl:sequence select=" 
   some $searchString in $searchStrings
   satisfies contains($arg,$searchString)
 "/>
</xsl:function>
    <xsl:variable name="additionalInfo" select="doc($additionalInfoPath)"/>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*[functx:contains-any-of(string-join(ancestor-or-self::*/upper-case(local-name()),'/'),$additionalInfo//AdditionalInfoData[@Type='ExtraInfo']/InfoDataValue/@TargetElement)]/text()">
                <xsl:value-of select="$additionalInfo//AdditionalInfoData[@Type='ExtraInfo']/InfoDataValue[contains(string-join(current()/ancestor-or-self::*/upper-case(local-name()),'/'),@TargetElement)]/text()"/>
    </xsl:template>
</xsl:stylesheet>

そして、置換するための値を提供する外部XMLドキュメント:

  <AdditionalInfoRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <AdditionalInfoData Type="ExtraInfo">
    <InfoDataValue Name="ITEM_1" TargetElement="ITEM_1" TargetElementValue="">111111</InfoDataValue>
    <InfoDataValue Name="LEVEL_1$ITEM_3" TargetElement="LEVEL_1/ITEM_3" TargetElementValue="">333333</InfoDataValue>
  </AdditionalInfoData>
</AdditionalInfoRoot>

外部ドキュメントでは、ターゲット要素の名前が大文字であり、それを制御できないことに注意してください。「LEVEL_1 / ITEM_3」などの理由で、ルートへの完全なxpathでcontainsを使用する必要があります。

この解決策は機能していますが、それはどういうわけか面倒であり、私が考案することができないより良い解決策があるに違いないと思います...

これを改善するための提案やヒントは大歓迎です!

Thxs Vlax

4

1 に答える 1

0

これはもっと簡単かもしれません

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

 <xsl:variable name="vLookupDoc">
   <t>
     <e path="ITEM_1">111111</e>
     <e path="LEVEL_1/ITEM_3">333333</e>
   </t> 
 </xsl:variable>

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

 <xsl:template match="text()">
  <xsl:variable name="vRep" select=
   "$vLookupDoc/*/e
      [ends-with(
        string-join(current()/ancestor::*[parent::*]/lower-case(name(.)), '/'),
        lower-case(@path)
                 )
      ]
       /string(.)
   "/>

   <xsl:sequence select="(., $vRep)[last()]"></xsl:sequence>
 </xsl:template>
</xsl:stylesheet>

この変換が提供されたXMLドキュメントに適用される場合:

<root>
    <level_1>
        <item_1>xxxxx</item_1>
        <item_2>yyyyy</item_2>
        <item_3>zzzzz</item_3>
    </level_1>
</root>

必要な正しい結果が生成されます。

<root>
      <level_1>
            <item_1>111111</item_1>
            <item_2>yyyyy</item_2>
            <item_3>333333</item_3>
      </level_1>
</root>
于 2012-08-11T16:09:44.887 に答える