XSLT:使用XSLT1.0规范化具有complexTypes的XML关系



用关系数据库的话说,我需要如何表达我需要做的是将(XML(关系从第二范式规范化为第三范式。请允许我举例解释:

示例XML输入

<?xml version="1.0" encoding="windows-1252"?>
<Root>
<RECORD>
<SESSIONID>303934</SESSIONID>
<CASEID>1051-2021</CASEID>
<CLIENTID>1051</CLIENTID>
<SCORETYPECODE>CIRCUMSTANCES</SCORETYPECODE>
<SCORECODE>TRAINING12</SCORECODE>
<ASSESSMENTPHASECODE>PRE</ASSESSMENTPHASECODE>
</RECORD>
<RECORD>
<SESSIONID>303934</SESSIONID>
<CASEID>1051-2021</CASEID>
<CLIENTID>1051</CLIENTID>
<SCORETYPECODE>CIRCUMSTANCES</SCORETYPECODE>
<SCORECODE>MATERIAL3</SCORECODE>
<ASSESSMENTPHASECODE>PRE</ASSESSMENTPHASECODE>
</RECORD>
<RECORD>
<SESSIONID>303805</SESSIONID>
<CASEID>2041-2021</CASEID>
<CLIENTID>2041</CLIENTID>
<SCORETYPECODE>GOALS</SCORETYPECODE>
<SCORECODE>CONFIDENCE1</SCORECODE>
<ASSESSMENTPHASECODE>POST</ASSESSMENTPHASECODE>
</RECORD>
<RECORD>
<SESSIONID>303805</SESSIONID>
<CASEID>2041-2021</CASEID>
<CLIENTID>2041</CLIENTID>
<SCORETYPECODE>SATISFACTION</SCORETYPECODE>
<SCORECODE>SITUATIONIMPROVED2</SCORECODE>
<ASSESSMENTPHASECODE>POST</ASSESSMENTPHASECODE>
</RECORD>
</Root>

以下是定义转换XML的XSD中最相关的部分:

XSD xnippet

...
<xs:element name="ClientAssessments" type="ClientAssessments"  maxOccurs="1">
<xs:unique name="UniqueClientAssessment">
<xs:selector xpath=".//ClientAssessment"/>
<xs:field xpath=".//ClientId"/>
<xs:field xpath=".//CaseId"/>
<xs:field xpath=".//SessionId"/>
</xs:unique>
</xs:element>
...
<xs:complexType name="ClientAssessments">
<xs:sequence>
<xs:element name="ClientAssessment" type="ClientAssessment" maxOccurs="unbounded" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
...
<xs:complexType name="ClientAssessment">
<xs:sequence>
<xs:element name="ClientId" type="NonEmptyOrLeadingTrailingSpacesString50Char" />
<xs:element name="CaseId" type="NonEmptyOrLeadingTrailingSpacesString50Char" />
<xs:element name="SessionId" type="NonEmptyOrLeadingTrailingSpacesString50Char" />
<xs:element name="Assessments">
<xs:complexType>
<xs:sequence>
<xs:element name="Assessment" type="Assessment" maxOccurs="6" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Assessment">
<xs:sequence>
<xs:element name="ScoreTypeCode" type="NonEmptyString" />
<xs:element name="AssessmentPhaseCode" type="NonEmptyString" />
<xs:element name="AssessedByCode" type="NonEmptyOrLeadingTrailingSpacesString" minOccurs="0" />
<xs:element name="Scores">
<xs:complexType>
<xs:sequence>
<xs:element  name="ScoreCode" type="NonEmptyString"  maxOccurs="unbounded" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
...

到目前为止,我创建了一个XSLT来转换为目的地的XML:

XSLT到目前为止

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="Root">
<ClientAssessments>
<xsl:apply-templates select="RECORD"/>
</ClientAssessments>
</xsl:template>
<xsl:template match="RECORD">
<ClientAssessment>
<SessionID><xsl:value-of select="SESSIONID"/></SessionID>
<CaseID><xsl:value-of select="CASEID"/></CaseID>
<ClientID><xsl:value-of select="CLIENTID"/></ClientID>
<Assessments>
<Assessment>
<ScoreTypeCode><xsl:value-of select="SCORETYPECODE"/></ScoreTypeCode>
<AssessmentPhaseCode><xsl:value-of select="ASSESSMENTPHASECODE"/></AssessmentPhaseCode>
<Scores>
<ScoreCode><xsl:value-of select="SCORECODE"/></ScoreCode>
</Scores>
</Assessment>
</Assessments>
</ClientAssessment>
</xsl:template>
</xsl:transform>

产生以下结果:

示例XML输出

<?xml version="1.0" encoding="utf-8"?>
<ClientAssessments>
<ClientAssessment>
<SessionID>303934</SessionID>
<CaseID>1051-2021</CaseID>
<ClientID>1051</ClientID>
<Assessments>
<Assessment>
<ScoreTypeCode>CIRCUMSTANCES</ScoreTypeCode>
<AssessmentPhaseCode>PRE</AssessmentPhaseCode>
<Scores>
<ScoreCode>TRAINING12</ScoreCode>
</Scores>
</Assessment>
</Assessments>
</ClientAssessment>
<ClientAssessment>
<SessionID>303934</SessionID>
<CaseID>1051-2021</CaseID>
<ClientID>1051</ClientID>
<Assessments>
<Assessment>
<ScoreTypeCode>CIRCUMSTANCES</ScoreTypeCode>
<AssessmentPhaseCode>PRE</AssessmentPhaseCode>
<Scores>
<ScoreCode>MATERIAL3</ScoreCode>
</Scores>
</Assessment>
</Assessments>
</ClientAssessment>
<ClientAssessment>
<SessionID>303805</SessionID>
<CaseID>2041-2021</CaseID>
<ClientID>2041</ClientID>
<Assessments>
<Assessment>
<ScoreTypeCode>GOALS</ScoreTypeCode>
<AssessmentPhaseCode>POST</AssessmentPhaseCode>
<Scores>
<ScoreCode>CONFIDENCE1</ScoreCode>
</Scores>
</Assessment>
</Assessments>
</ClientAssessment>
<ClientAssessment>
<SessionID>303805</SessionID>
<CaseID>2041-2021</CaseID>
<ClientID>2041</ClientID>
<Assessments>
<Assessment>
<ScoreTypeCode>SATISFACTION</ScoreTypeCode>
<AssessmentPhaseCode>POST</AssessmentPhaseCode>
<Scores>
<ScoreCode>SITUATIONIMPROVED2</ScoreCode>
</Scores>
</Assessment>
</Assessments>
</ClientAssessment>
</ClientAssessments>

到目前为止,一切都很好。但是,根据XSD,每个<ClientAssessment>节点中的<Assessments>子节点需要包含给定<ClientAssessment>(<SessionID>是其密钥(的所有<Assessment>节点。这就是它需要的样子:

所需的XML输出

<?xml version="1.0"?>
<ClientAssessments>
<ClientAssessment>
<SessionID>303934</SessionID>
<CaseID>1051-2021</CaseID>
<ClientID>1051</ClientID>
<Assessments>
<Assessment>
<ScoreTypeCode>CIRCUMSTANCES</ScoreTypeCode>
<AssessmentPhaseCode>PRE</AssessmentPhaseCode>
<Scores>
<ScoreCode>TRAINING12</ScoreCode>
</Scores>
</Assessment>
<Assessment>
<ScoreTypeCode>CIRCUMSTANCES</ScoreTypeCode>
<AssessmentPhaseCode>PRE</AssessmentPhaseCode>
<Scores>
<ScoreCode>MATERIAL3</ScoreCode>
</Scores>
</Assessment>
</Assessments>
</ClientAssessment>
<ClientAssessment>
<SessionID>303805</SessionID>
<CaseID>2041-2021</CaseID>
<ClientID>2041</ClientID>
<Assessments>
<Assessment>
<ScoreTypeCode>GOALS</ScoreTypeCode>
<AssessmentPhaseCode>POST</AssessmentPhaseCode>
<Scores>
<ScoreCode>CONFIDENCE1</ScoreCode>
</Scores>
</Assessment>
<Assessment>
<ScoreTypeCode>SATISFACTION</ScoreTypeCode>
<AssessmentPhaseCode>POST</AssessmentPhaseCode>
<Scores>
<ScoreCode>SITUATIONIMPROVED2</ScoreCode>
</Scores>
</Assessment>
</Assessments>
</ClientAssessment>
</ClientAssessments>

我希望我已经解释得足够好了。我该如何做到这一点;归一化";在XSLT1.0中?

后续问题:对于这样的转换,有人可以提出什么好的XSLT参考?我发现w3schools并没有真正涵盖足够的内容让我自己去想。

规范化是指您对模式所做的更改;您需要对实例进行的相应更改在XSLT领域中称为";分组";。XSLT教材和教程以及SO问答中都详细介绍了该主题。您需要知道的关键是,解决方案在XSLT2.0+中非常简单(使用xsl:for-each-group指令(,但在XSLT1.0中相当曲折(使用Muenchian分组(。因此,如果可能的话,请使用支持2.0+的处理器。

最新更新