void CModelReaderNode_BeamLattice1702_Beam::OnAttribute(_In_z_ const nfWChar * pAttributeName, _In_z_ const nfWChar * pAttributeValue)
	{
		__NMRASSERT(pAttributeName);
		__NMRASSERT(pAttributeValue);

		if (wcscmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_V1) == 0) {
			nfInt32 nValue = fnWStringToInt32(pAttributeValue);
			if ((nValue >= 0) && (nValue < XML_3MF_MAXRESOURCEINDEX))
				m_nIndex1 = nValue;
		}
		else if (wcscmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_V2) == 0) {
			nfInt32 nValue = fnWStringToInt32(pAttributeValue);
			if ((nValue >= 0) && (nValue < XML_3MF_MAXRESOURCEINDEX))
				m_nIndex2 = nValue;
		}
		else if (wcscmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_R1) == 0) {
			nfFloat fValue = fnWStringToFloat(pAttributeValue);
			if ((fValue >= 0) && (fValue < XML_3MF_MAXIMUMBEAMRADIUSVALUE)) {
				m_dRadius1 = fValue;
				m_bHasRadius1 = true;
			}
		}
		else if (wcscmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_R2) == 0) {
			nfFloat fValue = fnWStringToFloat(pAttributeValue);
			if ((fValue >= 0) && (fValue < XML_3MF_MAXIMUMBEAMRADIUSVALUE)) {
				m_dRadius2 = fValue;
				m_bHasRadius2 = true;
			}
		}
		else if (wcscmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_CAP1) == 0) {
			m_bHasCap1 = true;
			m_eCapMode1 = stringToCapMode(pAttributeValue);
		}
		else if (wcscmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_CAP2) == 0) {
			m_bHasCap2 = true;
			m_eCapMode2 = stringToCapMode(pAttributeValue);
		}
		else
			m_pWarnings->addException(CNMRException(NMR_ERROR_BEAMLATTICEINVALIDATTRIBUTE), mrwInvalidOptionalValue);
	}
	void CModelReaderNode_BeamLattice1702_BeamLattice::OnAttribute(_In_z_ const nfChar * pAttributeName, _In_z_ const nfChar * pAttributeValue)
	{
		__NMRASSERT(pAttributeName);
		__NMRASSERT(pAttributeValue);

		if (strcmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_RADIUS) == 0) {
			nfDouble dValue = fnStringToDouble(pAttributeValue);
			if ( std::isnan(dValue) || (dValue <= 0) || (dValue > XML_3MF_MAXIMUMCOORDINATEVALUE) )
				throw CNMRException(NMR_ERROR_BEAMLATTICEINVALIDATTRIBUTE);
			m_pMesh->setDefaultBeamRadius(dValue);
		}
		else if ( (strcmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_MINLENGTH) == 0) ||
			(strcmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_PRECISION) == 0) )	// legacy
		{
			nfDouble dValue = fnStringToDouble(pAttributeValue);
			if (std::isnan(dValue) || (dValue <= 0) || (dValue > XML_3MF_MAXIMUMCOORDINATEVALUE))
				throw CNMRException(NMR_ERROR_BEAMLATTICEINVALIDATTRIBUTE);
			m_pMesh->setBeamLatticeMinLength(dValue);
		}
		else if (strcmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_CLIPPING) == 0) {
			if (strcmp(pAttributeValue, XML_3MF_BEAMLATTICE_CLIPMODE_INSIDE) == 0) {
				m_eClipMode = MODELBEAMLATTICECLIPMODE_INSIDE;
			}
			else if (strcmp(pAttributeValue, XML_3MF_BEAMLATTICE_CLIPMODE_OUTSIDE) == 0) {
				m_eClipMode = MODELBEAMLATTICECLIPMODE_OUTSIDE;
			}
			else {
				m_eClipMode = MODELBEAMLATTICECLIPMODE_NONE;
			}
		}
		else if (strcmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_CLIPPINGMESH) == 0) {
			m_nClippingMeshID = fnStringToUint32(pAttributeValue);
			m_bHasClippingMeshID = true;
		}
		else if (strcmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_REPRESENTATIONMESH) == 0) {
			m_nRepresentationMeshID = fnStringToUint32(pAttributeValue);
			m_bHasRepresentationMeshID = true;
		}
		else if (strcmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_ACCURACY) == 0) {
			// legacy, ignore it
		}
		else if (strcmp(pAttributeName, XML_3MF_ATTRIBUTE_BEAMLATTICE_CAPMODE) == 0) {
			m_pMesh->setBeamLatticeCapMode(stringToCapMode(pAttributeValue));
		}
		else
			m_pWarnings->addException(CNMRException(NMR_ERROR_BEAMLATTICEINVALIDATTRIBUTE), mrwInvalidOptionalValue);
	}