1

xml と xslt にクエリがあります

以下は入力 XML です。

<?xml version="1.0" encoding="UTF-8"?>    
<Employer>
    <Employees>
        <EmployeesDetails>van ind 26%</EmployeesDetails>
    </Employees>    
    <Employees>
        <EmployeesDetails>van ind</EmployeesDetails>
    </Employees>    
</Employer>

上記は私の入力ファイルです

以下は私の出力ファイルです

<?xml version="1.0" encoding="UTF-8"?>
<Employer>
    <Employees>
        <Names>van</Names>
        <Location>ind</Location>                
        <Weather>26</Weather>
    </Employees>
    <Employees>
        <Names>van</Names>
        <Location>ind</Location>
        <Weather>100</Weather>
    </Employees>
</Employer>

以下の XSLT を上記の XML 入力に適用するにはどうすればよいですか?

4

2 に答える 2

1

I. この XSLT 2.0 変換:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 exclude-result-prefixes="xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <Employer>
    <xsl:apply-templates/>
  </Employer>
 </xsl:template>

 <xsl:template match="Employees">
  <xsl:variable name="vNames" select="tokenize(Names, ' ')"/>
  <xsl:variable name="vLoc" select="tokenize(Location, ' ')"/>
  <xsl:variable name="vWeather"
       select="tokenize(translate(Weather, '%', ' '), ' ')"/>
  <xsl:for-each select="$vNames">
    <xsl:variable name="vPos" select="position()" as="xs:integer"/>
    <Employees>
      <Names><xsl:sequence select="."/></Names>
      <Location>
        <xsl:sequence select="(lower-case($vLoc[$vPos]), 'Unknown')[1]"/>
      </Location>
      <Weather>
        <xsl:sequence select="($vWeather[$vPos], 100)[1]"/>
      </Weather>
    </Employees>
    </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

提供された XML ドキュメントに適用した場合:

<Employer>
    <Employees>
        <Names>vel bel sel tel mel</Names>
        <Location>IND AUS ENG CAL JAP</Location>
        <Weather>26%</Weather>
    </Employees>
    <Employees>
        <Names>asd sadl asdsel tdddel dmdel</Names>
        <Location>IND AUS ENG CAL JAP</Location>
    </Employees>
</Employer>

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

<Employer>
   <Employees>
      <Names>vel</Names>
      <Location>ind</Location>
      <Weather>26</Weather>
   </Employees>
   <Employees>
      <Names>bel</Names>
      <Location>aus</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>sel</Names>
      <Location>eng</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>tel</Names>
      <Location>cal</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>mel</Names>
      <Location>jap</Location>
      <Weather>100</Weather>
   </Employees>
      <Employees>
      <Names>asd</Names>
      <Location>ind</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>sadl</Names>
      <Location>aus</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>asdsel</Names>
      <Location>eng</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>tdddel</Names>
      <Location>cal</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>dmdel</Names>
      <Location>jap</Location>
      <Weather>100</Weather>
   </Employees>
</Employer>

注意してください:

私は次の合理的な仮定を立てました。

  1. あなたが実際に望む100のは、 ではありません100%

  2. Employeesこの要素の最初の出現だけでなく、すべてを処理する必要があります。

提供された場所の数が提供された名前の数よりも少ない場合に備えて、欠落している場所のデフォルト値も追加しました。


Ⅱ.XSLT 1.0 ソリューション:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 xmlns:my="my:my" exclude-result-prefixes="ext my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <my:defaults>
  <L>Unknown</L>
  <W>100</W>
 </my:defaults>

 <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
 <xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vDefaults" select="document('')/*/my:defaults"/>

 <xsl:template match="/*">
  <Employer>
   <xsl:apply-templates/>
  </Employer>
 </xsl:template>

 <xsl:template match="Employees">
  <xsl:variable name="vrtfNames">
   <xsl:apply-templates select="Names"/>
  </xsl:variable>
  <xsl:variable name="vNames" select="ext:node-set($vrtfNames)/*"/>
  <xsl:variable name="vrtfLocs">
   <xsl:apply-templates select="Location"/>
  </xsl:variable>
  <xsl:variable name="vrtfWeather">
   <xsl:apply-templates select="Weather"/>
  </xsl:variable>

  <xsl:apply-templates select="$vNames">
   <xsl:with-param name="pLocs" select="ext:node-set($vrtfLocs)/*"/>
   <xsl:with-param name="pWeather" select="ext:node-set($vrtfWeather)/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="s" priority="3">
  <xsl:param name="pLocs"/>
  <xsl:param name="pWeather"/>

  <xsl:variable name="vPos" select="position()"/>
  <Employees>
   <Names><xsl:value-of select="."/></Names>
   <Location>
     <xsl:value-of select=
       "translate($pLocs[position() = $vPos]
                   | $vDefaults[not($pLocs[position() = $vPos])]/L,
                  $vUpper, $vLower)"/>
   </Location>
   <Weather>
     <xsl:value-of select=
       "$pWeather[position() = $vPos]
      | $vDefaults[not($pWeather[position() = $vPos])]/W"/>
   </Weather>
  </Employees>
 </xsl:template>

 <xsl:template match="Weather">
  <xsl:call-template name="tokenize">
    <xsl:with-param name="pText" select="translate(., '%', ' ')"/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template match="Employees/*/text()" name="tokenize">
  <xsl:param name="pText" select="."/>

  <xsl:variable name="vText" select="normalize-space($pText)"/>
  <xsl:if test="$vText">
   <s>
    <xsl:value-of select="substring-before(concat($vText, ' '), ' ')"/>
   </s>

   <xsl:call-template name="tokenize">
    <xsl:with-param name="pText" select="substring-after($vText, ' ')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

この変換が提供された XML ドキュメント (上記) に適用されると、同じように正しい結果が生成されます。

<Employer>
   <Employees>
      <Names>vel</Names>
      <Location>ind</Location>
      <Weather>26</Weather>
   </Employees>
   <Employees>
      <Names>bel</Names>
      <Location>aus</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>sel</Names>
      <Location>eng</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>tel</Names>
      <Location>cal</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>mel</Names>
      <Location>jap</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>asd</Names>
      <Location>ind</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>sadl</Names>
      <Location>aus</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>asdsel</Names>
      <Location>eng</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>tdddel</Names>
      <Location>cal</Location>
      <Weather>100</Weather>
   </Employees>
   <Employees>
      <Names>dmdel</Names>
      <Location>jap</Location>
      <Weather>100</Weather>
   </Employees>
</Employer>

注意してください:

  1. 基本的に、XSLT 2.0 変換と同じロジックが実装されています。

  2. XPath 1.0 にはtokenizeorlower-case()関数がなく、XPath 1.0 データ モデルにはシーケンスの概念がないため、これらは (それぞれ) トークン化のテンプレートを使用して実装され、translate()小文字に変換する関数を使用し、要素を使用して実装されます。天気と場所のデフォルトが含まれています。

于 2012-07-07T23:14:12.857 に答える
0

あなたの質問は、いくつかの重要な分野で漠然としています。たとえば、ノードセットに<Employees>ノードがない<weather>場合は、値が 100%のノードを取得する必要があると述べているようです。とはいえ、期待される出力はそのロジックを一貫して適用していないようです。目的の<Location>結果ノードが大文字から小文字に変換されます。さらに、出力<Employees>はソース XML の 2 番目のノード セットを完全に無視しているようです。

EXSLTを使用する XSLT 1.0 ソリューションを次に示します。これがあなたの望むものではない場合は、質問をより具体的に更新してください。対応できるように努めます。

この XSLT の場合:

<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:exsl="http://exslt.org/common"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  exclude-result-prefixes="exsl" 
  version="1.0">

  <xsl:output omit-xml-declaration="no" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="Employees">
    <xsl:variable name="vNames">
      <xsl:call-template name="tokenize">
        <xsl:with-param name="text" select="Names/text()"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="vLocations">
      <xsl:call-template name="tokenize">
        <xsl:with-param name="text" select="Location/text()"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:apply-templates select="exsl:node-set($vNames)/token">
      <xsl:with-param name="pLocation"
          select="exsl:node-set($vLocations)/token"/>
      <xsl:with-param name="pWeather" select="Weather"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="token">
    <xsl:param name="pLocation"/>
    <xsl:param name="pWeather"/>
    <xsl:variable name="vPosition" select="position()"/>
    <Employees>
      <Names>
        <xsl:value-of select="."/>
      </Names>
      <Location>
        <xsl:value-of select="translate($pLocation[$vPosition],
            'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
      </Location>
      <xsl:choose>
        <xsl:when test="$pWeather != ''">
          <xsl:apply-templates select="$pWeather"/>
        </xsl:when>
        <xsl:otherwise>
          <Weather>100%</Weather>
        </xsl:otherwise>
      </xsl:choose>
    </Employees>
  </xsl:template>

  <xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="delimiter" select="' '"/>
    <xsl:choose>
      <xsl:when test="contains($text,$delimiter)">
        <xsl:element name="token">
          <xsl:value-of select="substring-before($text,$delimiter)"/>
        </xsl:element>
        <xsl:call-template name="tokenize">
          <xsl:with-param name="text"
              select="substring-after($text,$delimiter)"/>
          <xsl:with-param name="delimiter" select="$delimiter"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$text">
        <xsl:element name="token">
          <xsl:value-of select="$text"/>
        </xsl:element>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

...この XML に適用されます:

<?xml version="1.0"?>
<Employer>
  <Employees>
    <Names>vel bel sel tel mel</Names>
    <Location>IND AUS ENG CAL JAP</Location>
    <Weather>26%</Weather>
  </Employees>
  <Employees>
    <Names>asd sadl asdsel tdddel dmdel</Names>
    <Location>IND AUS ENG CAL JAP</Location>
  </Employees>
</Employer>

...目的の (?) 結果が生成されます。

<?xml version="1.0" encoding="UTF-8"?>
<Employer>
  <Employees>
    <Names>vel</Names>
    <Location>ind</Location>
    <Weather>26%</Weather>
  </Employees>
  <Employees>
    <Names>bel</Names>
    <Location>aus</Location>
    <Weather>26%</Weather>
  </Employees>
  <Employees>
    <Names>sel</Names>
    <Location>eng</Location>
    <Weather>26%</Weather>
  </Employees>
  <Employees>
    <Names>tel</Names>
    <Location>cal</Location>
    <Weather>26%</Weather>
  </Employees>
  <Employees>
    <Names>mel</Names>
    <Location>jap</Location>
    <Weather>26%</Weather>
  </Employees>
  <Employees>
    <Names>asd</Names>
    <Location>ind</Location>
    <Weather>100%</Weather>
  </Employees>
  <Employees>
    <Names>sadl</Names>
    <Location>aus</Location>
    <Weather>100%</Weather>
  </Employees>
  <Employees>
    <Names>asdsel</Names>
    <Location>eng</Location>
    <Weather>100%</Weather>
  </Employees>
  <Employees>
    <Names>tdddel</Names>
    <Location>cal</Location>
    <Weather>100%</Weather>
  </Employees>
  <Employees>
    <Names>dmdel</Names>
    <Location>jap</Location>
    <Weather>100%</Weather>
  </Employees>
</Employer>

説明:

  1. 最初のテンプレートであるID テンプレートは、すべての要素と属性をそのままコピーします。
  2. <Employee>要素に一致する 2 番目のテンプレートはtokenize、スペースで区切られた文字列を結果ツリーのフラグメントに分割する特別なテンプレートを実行します。これらのフラグメントは、便宜上変数に保存されます。
  3. 3 番目のテンプレートは、 という名前のすべての要素に一致しますtoken。これらは、EXSLT によって生成されます。EXSLT は、結果ツリー フラグメントを<token>要素で構成されるノード セットに変換します。これらのそれぞれについて、必要な要素値を取得して と を作成<Names><Location>ます。このテンプレートには、要素に必要な値を決定するために必要なロジックも含まれてい<weather>ます。
于 2012-07-07T22:45:23.093 に答える