1

前もってOK、私はPHPとJavaの初心者ですが、過去10年間管理に携わった後、コーディングを更新しようとしています。

次の形式のテーブルがあります。

heading1_sub1_element1 = data1
heading1_sub1_element2 = data2
heading1_sub1_element3 = data3
heading1_sub2_element1 = data4
heading1_sub2_element2 = data5
heading1_sub2_element3 = data6

Tony Marsdenのサイトのすばらしい例を使用して、データをフォームに抽出するためのテーブルを取得することができました。

<table>
    <heading1_sub1_element1>data1</heading1_sub1_element1>
    <heading1_sub1_element2>data2</heading1_sub1_element2>
    <heading1_sub1_element3>data3</heading1_sub1_element3>
    <heading1_sub2_element1>data4</heading1_sub2_element1>
    <heading1_sub2_element2>data5</heading1_sub2_element2>
    <heading1_sub2_element3>data6</heading1_sub2_element3>
</table>

しかし、私が行きたいのは:

<heading1>
    <sub1>
        <element1>Data1</element1>
        <element2>Data2</element2>
        <element3>Data3</element3>
    </sub1>
    <sub2>
        <element1>Data4</element1>
        <element2>Data5</element2>
        <element3>Data6</element3>
    </sub2>
</heading1>

データをその形式に変換する方法について誰かが何か考えを持っていますか?XSLTを使用する必要がありますか、それともPHPで直接使用できますか?

これを行う唯一の理由は、XMLの負荷全体が見栄えが良くなることです。

よろしくお願いします。どんな支援も大歓迎です。

4

3 に答える 3

2

これは、指定された形式の行のセットを正しく処理する一般的なソリューションです。各行にアンダースコアの数が異なり、最初の「名前」がすべての行で同じではない場合でも、次のようになります。

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

 <xsl:variable name="vLines" select="tokenize(/*, '\r?\n')[.]"/>

 <xsl:variable name="vPass1">
  <t>
   <xsl:apply-templates mode="pass1"/>
  </t>   
 </xsl:variable>


 <xsl:template match="/*" mode="pass1">
  <xsl:for-each select="$vLines">
   <xsl:sequence select="my:makeTree(normalize-space(.))"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="/">
  <xsl:apply-templates select="$vPass1" mode="pass2"/>
 </xsl:template>

 <xsl:function name="my:makeTree">
  <xsl:param name="pLine"/>

  <xsl:variable name="vName" select="substring-before($pLine, '_')"/>

  <xsl:choose>
    <xsl:when test="$vName">
      <xsl:element name="{$vName}">
        <xsl:sequence select="my:makeTree(substring-after($pLine, '_'))"/>
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
     <xsl:element name=
       "{normalize-space(substring-before($pLine, '='))}">
       <xsl:sequence select="substring-after($pLine, '=')"/>
     </xsl:element>
    </xsl:otherwise>
  </xsl:choose>
 </xsl:function>

 <xsl:function name="my:group">
  <xsl:param name="pNodes" as="node()*"/>

  <xsl:for-each-group select="$pNodes[self::*]" group-by="name()">
    <xsl:element name="{name()}">
      <xsl:for-each select="current-group()">
         <xsl:sequence select="my:group(node())"/>
      </xsl:for-each>
    </xsl:element>
  </xsl:for-each-group>
  <xsl:copy-of select="$pNodes[not(self::*)]"/>
 </xsl:function>

  <xsl:template match="*[not(my:path(.) = preceding::*/my:path(.))]" mode="pass2">
  <xsl:copy>
   <xsl:apply-templates select="//*[my:path(.) = my:path((current()))]/node()"
        mode="pass2"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*" mode="pass2"/>

 <xsl:template match="/*" mode="pass2" priority="3">
   <xsl:apply-templates mode="pass2"/>
 </xsl:template>

 <xsl:function name="my:path" as="xs:string">
  <xsl:param name="pElement" as="element()"/>

  <xsl:sequence select=
   "string-join($pElement/ancestor-or-self::*/name(.), '/')"/>
 </xsl:function>

</xsl:stylesheet>

この変換が次のXMLドキュメントに適用される場合(指定された行は、これを整形式のXMLドキュメントにするためにtop要素にラップされます):

<t>
    heading1_sub1_element1 = data1
    heading1_sub1_element2 = data2
    heading1_sub1_element3 = data3
    heading1_sub2_element1 = data4
    heading1_sub2_element2 = data5
    heading1_sub2_element3 = data6
</t>

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

<heading1>
   <sub1>
      <element1> data1</element1>
      <element2> data2</element2>
      <element3> data3</element3>
   </sub1>
   <sub2>
      <element1> data4</element1>
      <element2> data5</element2>
      <element3> data6</element3>
   </sub2>
</heading1>

これに同じ変換を適用すると、はるかに複雑なXMLドキュメント

<t>
    heading1_sub1_element1 = data1
    heading1_sub1_element2 = data2
    heading1_sub1_element3 = data3
    heading1_sub2_element1 = data4
    heading1_sub2_element2 = data5
    heading1_sub2_element3 = data6
    heading2_sub1_sub2_sub3 = data7
    heading2_sub1_sub2_sub3_sub4 = data8
    heading2_sub1_sub2 = data9
    heading2_sub1 = data10
    heading2_sub1_sub2_sub3 = data11
</t>

再び正しい、必要な結果が得られます

<heading1>
   <sub1>
      <element1> data1</element1>
      <element2> data2</element2>
      <element3> data3</element3>
   </sub1>
   <sub2>
      <element1> data4</element1>
      <element2> data5</element2>
      <element3> data6</element3>
   </sub2>
</heading1>
<heading2>
   <sub1>
      <sub2>
         <sub3>
            data7
            <sub4> data8</sub4>
            data11
         </sub3>
         data9
      </sub2>
      data10
  </sub1>
</heading2>

説明

これは2パス処理です。

  1. pass1では、入力を(上記の最初のXMLドキュメントの場合)次のような一時ツリーに変換します。

....。

<t>
   <heading1>
      <sub1>
         <element1> data1</element1>
      </sub1>
   </heading1>
   <heading1>
      <sub1>
         <element2> data2</element2>
      </sub1>
   </heading1>
   <heading1>
      <sub1>
         <element3> data3</element3>
      </sub1>
   </heading1>
   <heading1>
      <sub2>
         <element1> data4</element1>
      </sub2>
   </heading1>
   <heading1>
      <sub2>
         <element2> data5</element2>
      </sub2>
   </heading1>
   <heading1>
      <sub2>
         <element3> data6</element3>
      </sub2>
   </heading1>
</t>

.2。2番目のパスでは、特定の種類のグループ化を実行して、目的の結果を生成します。

:このソリューションでは、XMLドキュメント内の唯一の要素の唯一のテキストノードの子として入力文字列にアクセスします。この事実は必要ではなく、私は便宜のためだけにそうしました。標準のXSLT2.0関数を使用して、外部テキストファイルから文字列を読み取ることができますunparsed-text()

于 2012-05-25T04:21:52.497 に答える
1

個人的には、作成したXMLの最初のバージョンに本当に縛られていない限り、元のテキストファイル形式からすべてをphpで変換して、必要なXMLを作成します。はい、XSLを使用して最初の文字列から2番目の文字列に変換できますが、実際には、元の文字列をキーと値のペアに分割し、通常の式または文字列分割として、文字列をで分割する方がはるかに簡単です。 '_'文字を使用し、それをXML構造として使用します。使用する場合

$vals = explode("_", $string_input);

キーだけで、それは最初のもののためにあなたを与えるでしょう:

$vals[0] = "heading1";
$vals[1] = "sub1";
$vals[2] = "element1";

必要な構造を作成するために使用できます

私は通常、誰かに文字列を使用してXML構造を作成するようにアドバイスすることはありませんが(エンコーディングの問題が発生した場合)、そうしないと確信している場合は、文字列として出力するだけです(または、他の答えが言うように、simpleXML)。

于 2012-05-23T15:57:07.410 に答える
0

必要なノード名を解析するには、文字列操作を実行する必要があると確信していますが、その後、PHPのsimpleXMLを調べてください。これがその使い方を示す良い答えです。

于 2012-05-23T15:10:17.117 に答える