문제

다음과 같은 일부 계층적 XML을 변환하는 일반적인 방법이 있어야 합니다.

<element1 A="AValue" B="BValue">
   <element2 C="DValue" D="CValue">
      <element3 E="EValue1" F="FValue1"/>
      <element3 E="EValue2" F="FValue2"/>
   </element2>
   ...
</element1>

평면화된 XML(html)로 이동하면서 선택한 속성을 선택하고 열 헤더가 되는 속성에 대해 서로 다른 레이블을 제공합니다.

<table>
   <tr>
     <th>A_Label</th>
     <th>D_Label</th>
     <th>E_Label</th>
     <th>F_Label</th>
   </tr>
   <tr>
     <td>AValue</td>
     <td>DValue</td>
     <td>EValue1</td>
     <td>FValue1</td>
   </tr>
   <tr>
     <td>AValue</td>
     <td>DValue</td>
     <td>EValue2</td>
     <td>FValue2</td>
   </tr>
<table>

좋아요, 속성 재레이블링으로 인해 일반적인 해결책은 없지만 바라건대 제가 의미하는 바를 이해하실 수 있을 것입니다.나는 모든 XSLT/XPATH 관련 작업을 방금 시작했으므로 적절한 시기에 이를 해결하겠지만 어떤 단서도 유용할 것입니다.

도움이 되었습니까?

해결책

귀하가 하려는 작업이 무엇인지 100% 확신할 수는 없지만 element1, element2 및 element3이 일관되게 중첩된 경우 이 솔루션이 작동할 수 있습니다.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <table>
            <xsl:apply-templates select="//element3"></xsl:apply-templates>
        </table>
    </xsl:template>

    <xsl:template match="element3">
        <tr>
            <td><xsl:value-of select="../../@A"/></td>
            <td><xsl:value-of select="../../@B"/></td>
            <td><xsl:value-of select="../@C"/></td>
            <td><xsl:value-of select="../@D"/></td>
            <td><xsl:value-of select="@E"/></td>
            <td><xsl:value-of select="@F"/></td>
        </tr>
        <xsl:apply-templates select="*"></xsl:apply-templates>
    </xsl:template>

</xsl:stylesheet>

다른 팁

비슷한 XSLT가 필요했지만 깊이를 알 수 없었습니다. 수행 방법은 다음과 같습니다.

먼저, 결과 HTML 테이블/정의 목록에 대한 래퍼를 추가하고 템플릿 mode="puke"를 호출하여 XML 트리를 평면화합니다.

<xsl:element name="div">
    <xsl:attribute name="class" select="puke" />
    <xsl:apply-templates select="$notice" mode="puke" />
</xsl:element>  

여기서는 각 노드를 일치시켜 해당 콘텐츠를 표시합니다(예:text()) 및 해당 속성.우리는 이것을 재귀적으로 수행합니다.내 소스 트리가 .

<!-- @description: 
    Display all field from the notice so the customer can tell what he want
-->
<xsl:template match="node()" mode="puke">
<xsl:message>
    puking : <xsl:value-of select="local-name( . )" />
</xsl:message>
    <xsl:element name="dl">
        <xsl:element name="dt">
            <xsl:attribute name="class">tagName</xsl:attribute> 
            <xsl:value-of select="local-name( . )" />
        </xsl:element>
        <xsl:element name="dd">
            <xsl:attribute name="class">tagText</xsl:attribute>
            <xsl:value-of select="text()" /></xsl:element> 
        <xsl:element name="dl">
            <xsl:attribute name="class">attr</xsl:attribute>
            <!-- display attribute -->
            <xsl:apply-templates select="@*" />
        </xsl:element>
    </xsl:element>
    <!-- recursive call on node() -->
    <xsl:apply-templates select="./*" mode="puke" />    
</xsl:template>

특정 노드의 속성을 일치시켜 표시합니다.

CSS는 결과 HTML의 형식을 지정하는 데 사용됩니다.

<style>
.puke {
    background-color: #BDD6DE;
    clear: both;
}
.tagName, .attrName {
    float: left;
}
.tagText, .attrText {
    clear: right;
}
</style>

우리는 이미 Oracle 데이터베이스에서 읽는 Pro*C 프로그램을 가지고 있으며, 이는 Perl 스크립트를 호출하여 일부 Java를 실행하여 위에서 언급한 데이터베이스에서 XML 형식의 데이터를 추출하고 배치 파일을 호출하여 일부 vbscript를 실행합니다. 섬기는 사람.나는 Fortran에서 뭔가를 정말로 바랐습니다.

원래 질문을 명확히 해야 합니다.

  • 원래 질문에서 BValue와 CValue는 어떻게 되나요?평평한 구조의 일부가 되어서는 안 되는 이유가 있나요?
  • XML 문서의 모든 요소에는 2개의 속성이 있습니까? 아니면 완전히 임의적입니까?
  • 3가지 유형의 요소만 있고 예시에 표시된 대로 항상 중첩되어 있습니까?
  • element1이 자체적으로 반복될 수 있습니까? 아니면 이것이 문서의 루트 요소입니까?

XSLT에서는 매우 일반적인 변환기를 작성하는 것이 가능하지만 알려진 제한 사항을 고려할 수 있으면 문서를 변환하기 위한 스타일시트를 작성하는 것이 훨씬 더 쉽습니다.

구조화된 XML을 평면화하기 위해 아래 템플릿의 확장 버전을 사용했습니다.경고:원래 버전에는 방금 제거한 일부 사례별 코드(실제로 XML을 CSV로 변환)가 있었고 이 버전은 테스트하지 않았습니다.

기본 작동 방식은 다음과 같이 명확해야 합니다.노드 자식이 없는 모든 것을 인쇄하고 그렇지 않으면 자식이 있는 node()에서 템플릿을 재귀적으로 호출합니다.지금처럼 속성과 주석을 올바르게 처리하지 못한다고 생각하지만 수정하기 어렵지는 않습니다.

<?xml version="1.0" encoding="UTF-8"?>

<!-- XSL template to flatten structured XML, before converting to CSV. -->
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

    <xsl:strip-space elements="*" /> 

    <xsl:template match="/">
        <xsl:apply-templates select="//yourElementsToFlatten"/>
    </xsl:template>

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

    <xsl:template match="@*|node()">
        <xsl:choose>
            <!-- If the element has multiple childs, call this template 
                on its children to flatten it-->
            <xsl:when test="count(child::*) > 0">
                <xsl:apply-templates select="@*|node()"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:value-of select="text()" />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top